Initial code drop 36/636/1
authorRobert Varga <rovarga@cisco.com>
Wed, 24 Jul 2013 08:09:53 +0000 (10:09 +0200)
committerRobert Varga <rovarga@cisco.com>
Wed, 24 Jul 2013 08:16:49 +0000 (10:16 +0200)
This is the initial code drop, as passed through ICR on 07/10/2013.

Change-Id: Ia729cfc590629174fcd03a1a55dc667982f34d18
Signed-off-by: Robert Varga <rovarga@cisco.com>
847 files changed:
bgp/.gitignore [new file with mode: 0644]
bgp/.project [new file with mode: 0644]
bgp/concepts/.gitignore [new file with mode: 0644]
bgp/concepts/.project [new file with mode: 0644]
bgp/concepts/pom.xml [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ASPath.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ASSpecificExtendedCommunity.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/AbstractNextHop.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPAddressFamily.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPAggregator.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPObject.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPOrigin.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPSubsequentAddressFamily.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPTableType.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BaseBGPObjectState.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ClusterIdentifier.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/Community.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ExtendedCommunity.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/IPv4NextHop.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/IPv6NextHop.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/Inet4SpecificExtendedCommunity.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/NextHop.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/OpaqueExtendedCommunity.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/RouteOriginCommunity.java [new file with mode: 0644]
bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/RouteTargetCommunity.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/ASPathTest.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/ASSpecificExtendedCommunityTest.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/ClusterIdentifierTest.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/CommunityTest.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/IPv4NextHopTest.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/IPv6NextHopTest.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/Inet4SpecificExtendedCommunityTest.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/OpaqueExtendedCommunityTest.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/RouteOriginCommunityTest.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/RouteTargetCommunityTest.java [new file with mode: 0644]
bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/TableTypeTest.java [new file with mode: 0644]
bgp/linkstate/.project [new file with mode: 0644]
bgp/linkstate/pom.xml [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AbstractLANIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AbstractNetworkAddressRouterIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AbstractOSPFLANIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AdministrativeGroup.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AreaIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/DomainIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ExtendedRouteTag.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4InterfaceIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4PrefixIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4Route.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4RouterIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6InterfaceIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6PrefixIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6Route.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6RouterIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISAreaIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISLANIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISNetworkPrefix.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISNetworkPrefixState.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISRouterIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/InterfaceIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LANIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LinkAnchor.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LinkIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LinkProtectionType.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/MPLSProtocol.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkAddressRouterIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkLink.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkLinkImpl.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkLinkState.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkNode.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkNodeImpl.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkNodeState.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkObject.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkObjectImpl.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkObjectState.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkPrefix.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkPrefixState.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkRoute.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkRouteState.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NodeIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NodeIdentifierFactory.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFInterfaceIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFNetworkPrefix.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFNetworkPrefixState.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFPrefixIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFRouteType.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFRouterIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFv2LANIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFv3LANIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/PrefixIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/RouteTag.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/RouterIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/SourceProtocol.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/TopologyIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/TopologyNodeInformation.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/UniverseIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/UnnumberedLinkIdentifier.java [new file with mode: 0644]
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/AdministrativeGroupTest.java [new file with mode: 0644]
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/AreaIdentifierTest.java [new file with mode: 0644]
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/ISISAreaIdentifierTest.java [new file with mode: 0644]
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/LinkAnchorTest.java [new file with mode: 0644]
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/LinkIdentifierTest.java [new file with mode: 0644]
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/NodeIdentifierTest.java [new file with mode: 0644]
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/SharedRiskLinkGroupTest.java [new file with mode: 0644]
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/TopologyIdentifierTest.java [new file with mode: 0644]
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/TopologyNodeInformationTest.java [new file with mode: 0644]
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/UnnumberedLinkIdentifierTest.java [new file with mode: 0644]
bgp/parser-api/.gitignore [new file with mode: 0644]
bgp/parser-api/.project [new file with mode: 0644]
bgp/parser-api/pom.xml [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/AbstractBGPObjectState.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPDocumentedException.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPError.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPLink.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPLinkState.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPMessage.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPMessageHeader.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPMessageParser.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPNode.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPNodeState.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPParameter.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPParsingException.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPPrefix.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPPrefixState.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPRoute.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPRouteState.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPSession.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPSessionListener.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPUpdateEvent.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPUpdateMessage.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPUpdateSynchronized.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/message/BGPKeepAliveMessage.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/message/BGPNotificationMessage.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/message/BGPOpenMessage.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/AS4BytesCapability.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/CapabilityParameter.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/GracefulCapability.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/MultiprotocolCapability.java [new file with mode: 0644]
bgp/parser-api/src/site/apt/index.apt.vm [new file with mode: 0644]
bgp/parser-api/src/site/site.xml [new file with mode: 0644]
bgp/parser-api/src/test/java/org/opendaylight/protocol/bgp/parser/APITest.java [new file with mode: 0644]
bgp/parser-impl/.gitignore [new file with mode: 0644]
bgp/parser-impl/.project [new file with mode: 0644]
bgp/parser-impl/pom.xml [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/AbstractLinkstateMP.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPAggregatorImpl.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPIPv4PrefixMP.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPIPv6PrefixMP.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPLinkMP.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPMessageFactory.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPNodeMP.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateEventBuilder.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateMessageImpl.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/ByteList.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/IPv4MP.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/IPv6MP.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/IdentifierTlv.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/MPReach.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/PathAttribute.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPNotificationMessageParser.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPOpenMessageParser.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/BGPParameterParser.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/CapabilityParameterParser.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AsPathSegmentParser.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesParser.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LinkStateParser.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachParser.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/PathAttributeParser.java [new file with mode: 0644]
bgp/parser-impl/src/site/apt/index.apt.vm [new file with mode: 0644]
bgp/parser-impl/src/site/site.xml [new file with mode: 0644]
bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BGPParserTest.java [new file with mode: 0644]
bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateMessageParserTest.java [new file with mode: 0644]
bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/ComplementaryTest.java [new file with mode: 0644]
bgp/parser-impl/src/test/resources/bgp-update-nodes.txt [new file with mode: 0644]
bgp/parser-impl/src/test/resources/up1.bin [new file with mode: 0644]
bgp/parser-impl/src/test/resources/up10.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up11.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up12.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up13.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up14.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up15.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up16.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up17.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up2.bin [new file with mode: 0644]
bgp/parser-impl/src/test/resources/up3.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up4.bin [new file with mode: 0644]
bgp/parser-impl/src/test/resources/up5.bin [new file with mode: 0644]
bgp/parser-impl/src/test/resources/up6.bin [new file with mode: 0644]
bgp/parser-impl/src/test/resources/up7.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up8.bin [new file with mode: 0755]
bgp/parser-impl/src/test/resources/up9.bin [new file with mode: 0755]
bgp/parser-mock/.gitignore [new file with mode: 0644]
bgp/parser-mock/.project [new file with mode: 0644]
bgp/parser-mock/pom.xml [new file with mode: 0644]
bgp/parser-mock/src/main/java/org/opendaylight/protocol/bgp/parser/mock/BGPMessageParserMock.java [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up0.bin [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up1.bin [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up10.bin [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up2.bin [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up3.bin [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up4.bin [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up5.bin [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up6.bin [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up7.bin [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up8.bin [new file with mode: 0644]
bgp/parser-mock/src/main/resources/up9.bin [new file with mode: 0644]
bgp/parser-mock/src/site/apt/index.apt.vm [new file with mode: 0644]
bgp/parser-mock/src/site/site.xml [new file with mode: 0644]
bgp/parser-mock/src/test/java/org/opendaylight/protocol/bgp/parser/mock/BGPMessageParserMockTest.java [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up0.bin [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up1.bin [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up10.bin [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up2.bin [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up3.bin [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up4.bin [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up5.bin [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up6.bin [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up7.bin [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up8.bin [new file with mode: 0644]
bgp/parser-mock/src/test/resources/up9.bin [new file with mode: 0644]
bgp/pom.xml [new file with mode: 0644]
bgp/rib-api/.project [new file with mode: 0644]
bgp/rib-api/pom.xml [new file with mode: 0644]
bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/AbstractRIBChangeListener.java [new file with mode: 0644]
bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIB.java [new file with mode: 0644]
bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBChangedEvent.java [new file with mode: 0644]
bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBEvent.java [new file with mode: 0644]
bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBEventListener.java [new file with mode: 0644]
bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBSynchronizedEvent.java [new file with mode: 0644]
bgp/rib-impl/.project [new file with mode: 0644]
bgp/rib-impl/pom.xml [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGP.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPConnectionImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPDispatcherImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPInputStream.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPObjectComparator.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionFactory.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionProposalCheckerImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionProposalImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSynchronization.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPUpdateSynchronizedImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBEntry.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBTable.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPConnection.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPConnectionFactory.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPDispatcher.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionPreferences.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionProposal.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionProposalChecker.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ApiTest.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BGPImplTest.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/FSMTest.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/InputStreamTest.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/MockDispatcher.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserTest.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SimpleSessionListener.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SpeakerSessionListener.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SpeakerSessionMock.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SynchronizationTest.java [new file with mode: 0644]
bgp/rib-mock/.gitignore [new file with mode: 0644]
bgp/rib-mock/.project [new file with mode: 0644]
bgp/rib-mock/pom.xml [new file with mode: 0644]
bgp/rib-mock/src/main/java/org/opendaylight/protocol/bgp/rib/mock/BGPMock.java [new file with mode: 0644]
bgp/rib-mock/src/main/java/org/opendaylight/protocol/bgp/rib/mock/EventBusRegistration.java [new file with mode: 0644]
bgp/rib-mock/src/site/apt/index.apt.vm [new file with mode: 0644]
bgp/rib-mock/src/site/site.xml [new file with mode: 0644]
bgp/rib-mock/src/test/java/org/opendaylight/protocol/bgp/rib/mock/BGPListenerMock.java [new file with mode: 0644]
bgp/rib-mock/src/test/resources/BgpMessages [new file with mode: 0644]
bgp/rib-mock/src/test/resources/OpenMessage [new file with mode: 0644]
bgp/rib-mock/src/test/resources/bgp_hex.txt [new file with mode: 0644]
bgp/testtool/.gitignore [new file with mode: 0644]
bgp/testtool/.project [new file with mode: 0644]
bgp/testtool/pom.xml [new file with mode: 0644]
bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/Main.java [new file with mode: 0644]
bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/TestingListener.java [new file with mode: 0644]
bgp/testtool/src/main/resources/logback.xml [new file with mode: 0644]
bgp/testtool/src/test/java/org/opendaylight/protocol/bgp/testtool/BGPSpeakerMock.java [new file with mode: 0644]
bgp/testtool/src/test/java/org/opendaylight/protocol/bgp/testtool/SpeakerSessionListener.java [new file with mode: 0644]
bgp/util/.gitignore [new file with mode: 0644]
bgp/util/.project [new file with mode: 0644]
bgp/util/pom.xml [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/AbstractBGPObject.java [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/AbstractBGPPrefix.java [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/AbstractBGPRoute.java [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv4PrefixImpl.java [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv4RouteImpl.java [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv6PrefixImpl.java [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv6RouteImpl.java [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPLinkImpl.java [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPNodeImpl.java [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BinaryBGPDumpFileParser.java [new file with mode: 0644]
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/HexDumpBGPFileParser.java [new file with mode: 0644]
bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/BGPBinaryFileParserTest.java [new file with mode: 0644]
bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/BGPHexFileParserTest.java [new file with mode: 0644]
bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/LinkTest.java [new file with mode: 0644]
bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/NodeTest.java [new file with mode: 0644]
bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/PrefixTest.java [new file with mode: 0644]
bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/RouteTest.java [new file with mode: 0644]
bgp/util/src/test/resources/BgpMessage_Hex_InvalidLength [new file with mode: 0644]
bgp/util/src/test/resources/BgpMessages [new file with mode: 0644]
bgp/util/src/test/resources/BgpMessages_wrong_header [new file with mode: 0644]
bgp/util/src/test/resources/OpenMessage [new file with mode: 0644]
bgp/util/src/test/resources/bgp_hex.txt [new file with mode: 0644]
build/checkstyle/checkstyle-checker-api.xml [new file with mode: 0644]
build/checkstyle/checkstyle-checker.xml [new file with mode: 0644]
concepts/.gitignore [new file with mode: 0644]
concepts/.project [new file with mode: 0644]
concepts/bin/.gitignore [new file with mode: 0644]
concepts/bin/.project [new file with mode: 0644]
concepts/bin/pom.xml [new file with mode: 0644]
concepts/bin/src/site/apt/index.apt.vm [new file with mode: 0644]
concepts/bin/src/site/site.xml [new file with mode: 0644]
concepts/pom.xml [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/ASNumber.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractAddressFamily.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractIdentifier.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractMetric.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractPrefix.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/AddressFamily.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/Bandwidth.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/IGPMetric.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/IPAddresses.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/IPv4.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/IPv4Address.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/IPv4Prefix.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/IPv6.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/IPv6Address.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/IPv6Prefix.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/ISOSystemIdentifier.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/Identifier.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/Immutable.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/InitialListenerEvents.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/ListenerRegistration.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/Metric.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/NamedObject.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/NetworkAddress.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/Prefix.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/SharedRiskLinkGroup.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/State.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/Stateful.java [new file with mode: 0644]
concepts/src/main/java/org/opendaylight/protocol/concepts/TEMetric.java [new file with mode: 0644]
concepts/src/site/apt/index.apt.vm [new file with mode: 0644]
concepts/src/site/site.xml [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/ASNumberTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/AbstractIdentifierTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/AddressFamiliesTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/BandwidthTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/IGPMetricTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/IPAddressesAndPrefixesTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/IPv4AddressTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/IPv4PrefixTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/IPv6AddressTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/IPv6PrefixTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/ISOSystemIdentifierTest.java [new file with mode: 0644]
concepts/src/test/java/org/opendaylight/protocol/concepts/TEMetricTest.java [new file with mode: 0644]
framework/.gitignore [new file with mode: 0644]
framework/.project [new file with mode: 0644]
framework/pom.xml [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/DeserializerException.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/Dispatcher.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/DispatcherImpl.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/DocumentedException.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolConnection.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolConnectionFactory.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolInputStream.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolInputStreamFactory.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolMessage.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolMessageFactory.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolMessageHeader.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolOutputStream.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolServer.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSession.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionFactory.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SSLSelectableChannel.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SSLSelectionKey.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SSLSelector.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SSLServerSocketChannel.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SSLSocketChannel.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SessionListenerFactory.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SessionParent.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SessionPreferences.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SessionPreferencesChecker.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SessionPreferencesCheckerFactory.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SessionProposal.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SessionProposalFactory.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/SessionStreams.java [new file with mode: 0644]
framework/src/main/java/org/opendaylight/protocol/framework/TerminationReason.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/ComplementaryTest.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/Message.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/MessageFactory.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SecureServerTest.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/ServerTest.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/Session.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleInputStream.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleMessageFactory.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleSession.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionFactory.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionListener.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionListenerFactory.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionPreferences.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposal.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposalChecker.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposalCheckerFactory.java [new file with mode: 0644]
framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposalFactory.java [new file with mode: 0644]
framework/src/test/resources/keystore.jks [new file with mode: 0644]
framework/src/test/resources/logback-test.xml [new file with mode: 0644]
mockito-configuration/.gitignore [new file with mode: 0644]
mockito-configuration/.project [new file with mode: 0644]
mockito-configuration/bin/.gitignore [new file with mode: 0644]
mockito-configuration/bin/.project [new file with mode: 0644]
mockito-configuration/bin/pom.xml [new file with mode: 0644]
mockito-configuration/bin/src/main/java/org/mockito/configuration/ArgumentsExtractorVerifier.class [new file with mode: 0644]
mockito-configuration/bin/src/main/java/org/mockito/configuration/MockitoConfiguration.class [new file with mode: 0644]
mockito-configuration/bin/src/main/java/org/mockito/configuration/ThrowsUnstubbedMethodException.class [new file with mode: 0644]
mockito-configuration/bin/src/main/java/org/mockito/configuration/UnstubbedMethodException.class [new file with mode: 0644]
mockito-configuration/bin/src/main/resources/logback-test.xml [new file with mode: 0644]
mockito-configuration/bin/src/test/java/org/mockito/configuration/ArgumentsExtractorVerifierTest.class [new file with mode: 0644]
mockito-configuration/bin/src/test/java/org/mockito/configuration/DefaultAnswerTest.class [new file with mode: 0644]
mockito-configuration/pom.xml [new file with mode: 0644]
mockito-configuration/src/main/java/org/mockito/configuration/ArgumentsExtractorVerifier.java [new file with mode: 0644]
mockito-configuration/src/main/java/org/mockito/configuration/MockitoConfiguration.java [new file with mode: 0644]
mockito-configuration/src/main/java/org/mockito/configuration/ThrowsUnstubbedMethodException.java [new file with mode: 0644]
mockito-configuration/src/main/java/org/mockito/configuration/UnstubbedMethodException.java [new file with mode: 0644]
mockito-configuration/src/main/resources/logback-test.xml [new file with mode: 0644]
mockito-configuration/src/test/java/org/mockito/configuration/ArgumentsExtractorVerifierTest.java [new file with mode: 0644]
mockito-configuration/src/test/java/org/mockito/configuration/DefaultAnswerTest.java [new file with mode: 0644]
pcep/.gitignore [new file with mode: 0644]
pcep/.project [new file with mode: 0644]
pcep/api/.gitignore [new file with mode: 0644]
pcep/api/.project [new file with mode: 0644]
pcep/api/pom.xml [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPCloseTermination.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPConnection.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPConnectionFactory.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPDeserializerException.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPDispatcher.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPDocumentedException.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPErrorTermination.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPErrors.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPOFCodes.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSession.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionFactory.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionListener.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionListenerFactory.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionPreferences.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposal.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposalChecker.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposalCheckerFactory.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposalFactory.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/AbstractExtendedTunnelIdentifier.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/AggregateBandwidthConsumptionMetric.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/CumulativeIGPCostMetric.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/CumulativeTECostMetric.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/ExtendedTunnelIdentifier.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/IPv4ExtendedTunnelIdentifier.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/IPv6ExtendedTunnelIdentifier.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/LSPIdentifier.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/LSPSymbolicName.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/MostLoadedLinkLoadMetric.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/P2MPHopCountMetric.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/P2MPIGPMetric.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/P2MPTEMetric.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/TunnelIdentifier.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/UnnumberedInterfaceIdentifier.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCCreateMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPCloseMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPErrorMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPKeepAliveMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPNotificationMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPOpenMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPReplyMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPReportMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPRequestMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPUpdateRequestMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPXRAddTunnelMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPXRDeleteTunnelMessage.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeErrorObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeInstantiationObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeNotifyObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositePathObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeReplySvecObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeRequestObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeRequestSvecObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeResponseObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeRptPathObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeStateReportObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeUpdPathObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeUpdateRequestObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPBandwidthObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPBranchNodeListObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPBranchNodeObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPClassTypeObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPCloseObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPEndPoints.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPEndPointsObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPErrorObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPExcludeRouteObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPExistingPathBandwidthObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPExplicitRouteObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPGlobalConstraintsObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPIncludeRouteObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPLoadBalancingObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPLspObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPLspaObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPMetricObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPNoPathObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPNonBranchNodeListObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPNotificationObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPObjectiveFunctionObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPOpenObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPP2MPEndPointsObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPReportedRouteObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPRequestParameterObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPRequestedPathBandwidthObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPSecondaryExplicitRouteObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPSecondaryRecordRouteObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPSvecObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPUnreachedDestinationObject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROAsNumberSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROExplicitExclusionRouteSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROGeneralizedLabelSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROIPPrefixSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROLabelSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROPathKeyWith128PCEIDSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROPathKeyWith32PCEIDSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROProtectionSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROProtectionType1Subobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROProtectionType2Subobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROType1LabelSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROUnnumberedInterfaceSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROWavebandSwitchingLabelSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/ExcludeRouteSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/ExplicitRouteSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROAsNumberSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROAttributesSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROGeneralizedLabelSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROIPAddressSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROLabelSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROPathKeyWith128PCEIDSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROPathKeyWith32PCEIDSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROProtectionSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROProtectionType1Subobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROProtectionType2Subobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROType1LabelSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROUnnumberedInterfaceSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROWavebandSwitchingLabelSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/ReportedRouteSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROAsNumberSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROIPPrefixSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROSRLGSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROSubobjectAttribute.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROUnnumberedInterfaceSubobject.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/AbstractLSPIdentifiersTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/ByPassTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/IPv4LSPIdentifiersTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/IPv6LSPIdentifiersTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPCleanupTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPIdentifiersTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPStateDBVersionTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPSymbolicNameTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPUpdateErrorTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/NoPathVectorTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/NodeIdentifierTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/OFListTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/OrderTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/OverloadedDurationTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/P2MPCapabilityTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/PCEStatefulCapabilityTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/RSVPErrorSpecTlv.java [new file with mode: 0644]
pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/ReqMissingTlv.java [new file with mode: 0644]
pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/APITest.java [new file with mode: 0644]
pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/ConceptsTest.java [new file with mode: 0644]
pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/MessagesTest.java [new file with mode: 0644]
pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/ObjectsTest.java [new file with mode: 0644]
pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/TlvsTest.java [new file with mode: 0644]
pcep/api/src/test/resources/.gitignore [new file with mode: 0644]
pcep/impl/.gitignore [new file with mode: 0644]
pcep/impl/.project [new file with mode: 0644]
pcep/impl/pom.xml [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPConnectionImpl.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPDispatcherImpl.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPEROSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPInputStream.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageFactory.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageHeader.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPOFCodesMapping.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectFactory.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectHeader.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectIdentifier.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPRROSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionFactoryImpl.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionImpl.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionProposalCheckerFactoryImpl.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionProposalFactoryImpl.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionRuntimeMXBean.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPTlvParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPXROSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/Util.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCCreateMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCCreateMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPCloseMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPCloseMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPErrorMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPErrorMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPKeepAliveMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPKeepAliveMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPNotificationMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPNotificationMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPOpenMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPOpenMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPRawMessage.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReplyMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReplyMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReportMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReportMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPRequestMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPRequestMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPUpdateRequestMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPUpdateRequestMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRAddTunnelMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRAddTunnelMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRDeleteTunnelMessageParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRDeleteTunnelMessageValidator.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPBranchNodeListObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPClassTypeObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPCloseObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPEndPointsIPv4ObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPEndPointsIPv6ObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPErrorObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPExcludeRouteObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPExistingPathBandwidthObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPExplicitRouteObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPGlobalConstraintsObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPIncludeRouteObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPLoadBalancingObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPLspObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPLspaObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPMetricObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPNoPathObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPNonBranchNodeListObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPNotificationObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPObjectiveFunctionObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPOpenObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPP2MPEndPointsIPv4ObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPP2MPEndPointsIPv6ObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPReportedRouteObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPRequestParameterObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPRequestedPathBandwidthObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPSecondaryExplicitRouteObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPSecondaryRecordRouteObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPSvecObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPUnreachedIPv4DestinationObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPUnreachedIPv6DestinationObjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/UnknownObject.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROAsNumberSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROExplicitExclusionRouteSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROGeneralizedLabelSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROIPv4PrefixSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROIPv6PrefixSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROLabelParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROLabelSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROPathKeyWith128PCEIDSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROPathKeyWith32PCEIDSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionType1SubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionType2SubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROType1LabelSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROUnnumberedInterfaceSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROWavebandSwitchingLabelSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROAsNumberSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROAttributesSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROGeneralizedLabelSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROIPv4AddressSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROIPv6AddressSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROLabelParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROLabelSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROPathKeyWith128PCEIDSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROPathKeyWith32PCEIDSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionType1SubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionType2SubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROType1LabelSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROUnnumberedInterfaceSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROWavebandSwitchingLabelSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROAsNumberSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROIPv4PrefixSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROIPv6PrefixSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROSRLGSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROSubobjectAttributeMapping.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROUnnumberedInterfaceSubobjectParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/LSPIdentifierIPv4TlvParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/LSPIdentifierIPv6TlvParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/NoPathVectorTlvParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/OFListTlvParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/PCEStatefulCapabilityTlvParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/RSVPErrorSpecIPv4TlvParser.java [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/RSVPErrorSpecIPv6TlvParser.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/CompositeTest.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/FiniteStateMachineTest.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/MockDispatcher.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/MockPCE.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPObjectParserTest.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPSubobjectParserTest.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPTlvParserTest.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPValidatorTest.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPXROSubobjectParserTest.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/ServerSessionMock.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/SimpleSessionListener.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/SimpleSessionProposalChecker.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/tlv/LSPStateDBVersionTlvParserTest.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/tlv/PCEStatefulCapabilityTlvParserTest.java [new file with mode: 0644]
pcep/impl/src/test/resources/Close.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/Keepalive.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/LSPStateDBVersionTlv1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/LSPStateDBVersionTlv2.bin [new file with mode: 0644]
pcep/impl/src/test/resources/LSPStateDBVersionTlvInvalid1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/NoPathObject1WithTLV.bin [new file with mode: 0644]
pcep/impl/src/test/resources/NoPathObject2WithoutTLV.bin [new file with mode: 0644]
pcep/impl/src/test/resources/Open.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/Open.1.pbin [new file with mode: 0644]
pcep/impl/src/test/resources/Open.3.bin [new file with mode: 0644]
pcep/impl/src/test/resources/Open.invalid.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCClose.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPBandwidthObject1LowerBounds.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPBandwidthObject2UpperBounds.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPCloseMessage1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPCloseObject1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPEndPointsObject1IPv4.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPEndPointsObject2IPv6.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPErrorObject1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPErrorObject2Invalid.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPErrorObject3.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPExcludeRouteObject.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPExplicitRouteObject1PackOfSubobjects.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPGlobalConstraintsObject.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPIncludeRouteObject1PackOfSubobjects.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPKeepAliveMessage1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPLoadBalancingObject1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPLspObject1NoTlvsUpperBounds.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPLspaObject1LowerBounds.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPLspaObject2UpperBounds.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPLspaObject3RandVals.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPMetricObject1LowerBounds.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPMetricObject2UpperBounds.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPNotificationObject1WithTlv.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPNotificationObject2WithoutTlv.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPObject1UnknownClass.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPObject2UnknownType.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPObjectiveFunctionObject.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPOpenMessage1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPOpenObject1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPOpenObject2UpperBoundsNoTlv.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPOpenObject3.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPRPObject1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPRPObject2.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPReplyMessage1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPReportedRouteObject1PackOfSubobjects.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPRequestMessage1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPSvecObject1_10ReqIDs.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEPSvecObject2.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEStatefulCapabilityTlv1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEStatefulCapabilityTlv2.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCEStatefulCapabilityTlvInvalid1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCErr.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCErr.2.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCErr.3.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCErr.3b.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCErr.4.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCErr.5.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCErr.invalid.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCNtf.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCNtf.2.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCNtf.3.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCNtf.4.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCNtf.5.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCNtf.invalid.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRep.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRep.2.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRep.3.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRep.4.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRep.5.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRep.invalid.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCReq.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCReq.2.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCReq.3.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCReq.4.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCReq.5.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCReq.6.invalid.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCReq.invalid.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRpt.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRpt.2.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRpt.3.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRpt.4.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRpt.5.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCRpt.invalid.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCUpd.1.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCUpd.2.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCUpd.3.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCUpd.4.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCUpd.5.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PCUpd.invalid.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PackOfSubobjects.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PackOfTlvs.bin [new file with mode: 0644]
pcep/impl/src/test/resources/PackOfXROSubobjects.bin [new file with mode: 0644]
pcep/pom.xml [new file with mode: 0644]
pcep/testtool/.gitignore [new file with mode: 0644]
pcep/testtool/AutoResponseMessagesGenerator.groovy [new file with mode: 0644]
pcep/testtool/PeriodicallySendMessagesGenerator.groovy [new file with mode: 0644]
pcep/testtool/SendNowMessagesGenerator.groovy [new file with mode: 0644]
pcep/testtool/pom.xml [new file with mode: 0644]
pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/Main.java [new file with mode: 0644]
pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/MessageGeneratorService.java [new file with mode: 0644]
pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/SessionListenerFactory.java [new file with mode: 0644]
pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/SimpleSessionListener.java [new file with mode: 0644]
pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/TestingSessionListener.java [new file with mode: 0644]
pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/TestingSessionListenerFactory.java [new file with mode: 0644]
pcep/testtool/src/main/resources/GroovyReplyMessageGenerator.groovy [new file with mode: 0644]
pcep/testtool/src/test/java/org/opendaylight/protocol/pcep/testtool/PCCMock.java [new file with mode: 0644]
pcep/testtool/src/test/java/org/opendaylight/protocol/pcep/testtool/PCEPTestingToolTest.java [new file with mode: 0644]
pom.xml [new file with mode: 0644]
src/site/apt/index.apt.vm [new file with mode: 0644]
src/site/site.xml [new file with mode: 0644]
util/.gitignore [new file with mode: 0644]
util/.project [new file with mode: 0644]
util/pom.xml [new file with mode: 0644]
util/src/main/java/org/opendaylight/protocol/util/ByteArray.java [new file with mode: 0644]
util/src/main/java/org/opendaylight/protocol/util/DefaultingTypesafeContainer.java [new file with mode: 0644]
util/src/main/java/org/opendaylight/protocol/util/RemoveOnlySet.java [new file with mode: 0644]
util/src/main/java/org/opendaylight/protocol/util/SSLUtil.java [new file with mode: 0644]
util/src/main/java/org/opendaylight/protocol/util/TypesafeContainer.java [new file with mode: 0644]
util/src/site/apt/index.apt.vm [new file with mode: 0644]
util/src/site/site.xml [new file with mode: 0644]
util/src/test/java/org/opendaylight/protocol/util/ByteArrayTest.java [new file with mode: 0644]
util/src/test/resources/PCEStatefulCapabilityTlv1.bin [new file with mode: 0644]

diff --git a/bgp/.gitignore b/bgp/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/bgp/.project b/bgp/.project
new file mode 100644 (file)
index 0000000..138a061
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>bgp-subsystem</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.m2e.core.maven2Builder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/bgp/concepts/.gitignore b/bgp/concepts/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/bgp/concepts/.project b/bgp/concepts/.project
new file mode 100644 (file)
index 0000000..d0bd756
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>bgp-concepts</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bgp/concepts/pom.xml b/bgp/concepts/pom.xml
new file mode 100644 (file)
index 0000000..e496dce
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>bgp-parent</artifactId>
+        <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-concepts</artifactId>
+       <description>Basic BGP concepts</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+    <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.code.findbugs</groupId>
+                       <artifactId>jsr305</artifactId>
+                       <version>2.0.1</version>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.bgp.concepts
+                                               </Export-Package>
+                                               <Import-Package>
+                                                       com.google.common.base,
+                                                       org.opendaylight.protocol.concepts,
+                                                       com.google.guava,
+                                                       org.opendaylight.protocol.util
+                                               </Import-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>${checkstyle.version}</version>
+                               <configuration>
+                                       <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+                                       <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>BGP-CONCEPTS Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ASPath.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ASPath.java
new file mode 100644 (file)
index 0000000..0f527b5
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Conceptual representation of an AS path. This class distills the concept behind the encoding rules specified in RFC
+ * 4271.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-5.1.2">AS Path</a>
+ */
+public final class ASPath implements Serializable {
+       /**
+        * An empty AS Path (attribute in all UPDATE messages sent to internal peers).
+        */
+       public static final ASPath EMPTY = new ASPath();
+       private static final long serialVersionUID = 7951172606939897308L;
+       private final Set<ASNumber> aggregatedAsPath;
+       private final List<ASNumber> visibleAsPath;
+
+       private ASPath() {
+               this.visibleAsPath = Collections.emptyList();
+               this.aggregatedAsPath = Collections.emptySet();
+       }
+
+       /**
+        * Construct an AS path object representing a fully-visible path.
+        * 
+        * @param visibleAsPath Ordered list of AS numbers in the path, corresponding to the concatenation of all
+        *        AS_SEQUENCE components.
+        */
+       public ASPath(final List<ASNumber> visibleAsPath) {
+               this.aggregatedAsPath = Collections.emptySet();
+               this.visibleAsPath = Collections.unmodifiableList(Preconditions.checkNotNull(visibleAsPath));
+       }
+
+       /**
+        * Construct an AS path object representing a partially aggregated path.
+        * 
+        * @param visibleAsPath Ordered list of AS numbers in the path, corresponding to the concatenation of all
+        *        AS_SEQUENCE components.
+        * @param aggregatedAsPath Unordered set of AS numbers in the path, corresponding to the concatenation of all AS_SET
+        *        components.
+        */
+       public ASPath(final List<ASNumber> visibleAsPath, final Set<ASNumber> aggregatedAsPath) {
+               Preconditions.checkNotNull(aggregatedAsPath);
+               Preconditions.checkNotNull(visibleAsPath);
+               this.aggregatedAsPath = Collections.unmodifiableSet(aggregatedAsPath);
+               this.visibleAsPath = Collections.unmodifiableList(visibleAsPath);
+       }
+
+       /**
+        * Return the visible part of an AS path. Note that an AS number may be present multiple times in a row due to
+        * "AS number prepend" feature used by many routers to affect route decisions by extending the length on the list
+        * while keeping the loop information intact.
+        * 
+        * @return Ordered list of AS numbers.
+        */
+       public List<ASNumber> getVisibleAsPath() {
+               return this.visibleAsPath;
+       }
+
+       /**
+        * Return the aggregated part of an AS path.
+        * 
+        * @return Unordered set of AS numbers.
+        */
+       public Set<ASNumber> getAggregatedAsPath() {
+               return this.aggregatedAsPath;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.aggregatedAsPath == null) ? 0 : this.aggregatedAsPath.hashCode());
+               result = prime * result + ((this.visibleAsPath == null) ? 0 : this.visibleAsPath.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final ASPath other = (ASPath) obj;
+               if (this.aggregatedAsPath == null) {
+                       if (other.aggregatedAsPath != null)
+                               return false;
+               } else if (!this.aggregatedAsPath.equals(other.aggregatedAsPath))
+                       return false;
+               if (this.visibleAsPath == null) {
+                       if (other.visibleAsPath != null)
+                               return false;
+               } else if (!this.visibleAsPath.equals(other.visibleAsPath))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("aggregatedAsPath", this.aggregatedAsPath);
+               toStringHelper.add("visibleAsPath", this.visibleAsPath);
+               return toStringHelper;
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ASSpecificExtendedCommunity.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ASSpecificExtendedCommunity.java
new file mode 100644 (file)
index 0000000..bbefef0
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import java.io.Serializable;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class representing an <a href="http://tools.ietf.org/html/rfc4360#section-3.1">Two-Octet AS Specific Extended
+ * Community</a>.
+ */
+public class ASSpecificExtendedCommunity extends ExtendedCommunity implements Serializable {
+       private static final long serialVersionUID = 6490173838144366385L;
+       private final ASNumber globalAdmin;
+       private final byte[] localAdmin;
+       private final int subType;
+
+       /**
+        * Construct a new Two-Octet AS Specific Extended Community.
+        * 
+        * @param transitive True if this community is transitive
+        * @param subType Community subtype, has to be in range 0-255
+        * @param globalAdmin Globally-assigned namespace (AS number)
+        * @param localAdmin Locally-assigned value, has to be 4 bytes long
+        */
+       public ASSpecificExtendedCommunity(final boolean transitive, final int subType, final ASNumber globalAdmin, final byte[] localAdmin) {
+               super(false, transitive);
+               Preconditions.checkArgument(subType > 0 && subType < 255, "Invalid Sub-Type");
+               Preconditions.checkArgument(localAdmin.length == 4, "Invalid Local Administrator");
+               this.subType = subType;
+               this.globalAdmin = Preconditions.checkNotNull(globalAdmin);
+               this.localAdmin = localAdmin;
+       }
+
+       /**
+        * @return Community subtype
+        */
+       public final int getSubType() {
+               return this.subType;
+       }
+
+       /**
+        * @return Globally-assigned namespace
+        */
+       public final ASNumber getGlobalAdmin() {
+               return this.globalAdmin;
+       }
+
+       /**
+        * @return Locally-assigned value
+        */
+       public final byte[] getLocalAdmin() {
+               return this.localAdmin;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("subType", this.subType);
+               toStringHelper.add("globalAdmin", this.globalAdmin);
+               toStringHelper.add("localAdmin", this.localAdmin);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/AbstractNextHop.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/AbstractNextHop.java
new file mode 100644 (file)
index 0000000..76a56d6
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Abstract implementation of a NextHop class. This is a useful base class
+ * implementing all the required semantics for a NextHop. Subclasses only
+ * need to supply an appropriate public constructor.
+ *
+ * @param <T> template reference to subclass
+ */
+public abstract class AbstractNextHop<T extends NetworkAddress<T>> implements NextHop<T> {
+       private static final long serialVersionUID = 2462286640242941943L;
+       private final T global;
+       private final T linkLocal;
+
+       protected AbstractNextHop(final T global, final T linkLocal) {
+               this.global = Preconditions.checkNotNull(global);
+               this.linkLocal = linkLocal;
+       }
+
+       @Override
+       public T getGlobal() {
+               return global;
+       }
+
+       @Override
+       public T getLinkLocal() {
+               return linkLocal;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((global == null) ? 0 : global.hashCode());
+               result = prime * result
+                               + ((linkLocal == null) ? 0 : linkLocal.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final AbstractNextHop<?> other = (AbstractNextHop<?>) obj;
+               if (global == null) {
+                       if (other.global != null)
+                               return false;
+               } else if (!global.equals(other.global))
+                       return false;
+               if (linkLocal == null) {
+                       if (other.linkLocal != null)
+                               return false;
+               } else if (!linkLocal.equals(other.linkLocal))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("global", global);
+               toStringHelper.add("linkLocal", linkLocal);
+               return toStringHelper;
+       }
+
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPAddressFamily.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPAddressFamily.java
new file mode 100644 (file)
index 0000000..04d2a2b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import org.opendaylight.protocol.concepts.AddressFamily;
+
+/**
+ * Enumeration of all supported address families.
+ */
+public enum BGPAddressFamily {
+       /**
+        * IP (IP version 4)
+        */
+       IPv4(org.opendaylight.protocol.concepts.IPv4.FAMILY),
+       /**
+        * IP6 (IP version 6)
+        */
+       IPv6(org.opendaylight.protocol.concepts.IPv6.FAMILY),
+       /**
+        * Link State Information
+        */
+       LinkState(null);
+
+       private final AddressFamily<?> family;
+
+       private BGPAddressFamily(final AddressFamily<?> family) {
+               this.family = family;
+       }
+
+       /**
+        * Return the associated address family class.
+        * 
+        * @return associated address family class
+        */
+       public AddressFamily<?> getAddressFamily() {
+               return family;
+       }
+}
+
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPAggregator.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPAggregator.java
new file mode 100644 (file)
index 0000000..caf6a44
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * 
+ * BGP Path Attribute AGGREGATOR.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-5.1.7">BGP Aggregator</a>
+ * 
+ */
+public interface BGPAggregator {
+
+       /**
+        * The BGP Speaker returns its own AS Number.
+        * 
+        * @return own AS Number
+        */
+       public ASNumber getASNumber();
+
+       /**
+        * The BGP Speaker returns its own IP Address.
+        * 
+        * @return own IP Address
+        */
+       public NetworkAddress<?> getNetworkAddress();
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPObject.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPObject.java
new file mode 100644 (file)
index 0000000..e9272b5
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import java.io.Serializable;
+
+import org.opendaylight.protocol.concepts.Stateful;
+
+/**
+ * 
+ * A common interface for objects that can be added to a topology. It can be either BGPRoute, BGPLink, BGPNode or
+ * BGPPrefix.
+ * 
+ */
+public interface BGPObject extends Serializable, Stateful<BaseBGPObjectState> {
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPOrigin.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPOrigin.java
new file mode 100644 (file)
index 0000000..40069a4
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+/**
+ * 
+ * Values of BGP Origin Path Attribute.
+ * 
+ */
+public enum BGPOrigin {
+       IGP, EGP, INCOMPLETE
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPSubsequentAddressFamily.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPSubsequentAddressFamily.java
new file mode 100644 (file)
index 0000000..ba237e8
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+/**
+ * Enumeration of all supported subsequent address family identifiers.
+ */
+public enum BGPSubsequentAddressFamily {
+       /**
+        * RFC4760: Network Layer Reachability Information used
+        * for unicast forwarding.
+        */
+       Unicast,
+       /**
+        * RFC4364: MPLS-labeled VPN address
+        */
+       MPLSLabeledVPN,
+       /**
+        * draft-ietf-idr-ls-distribution-03 : Linkstate SAFI
+        */
+       Linkstate
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPTableType.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BGPTableType.java
new file mode 100644 (file)
index 0000000..cc4c6dc
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import com.google.common.base.Preconditions;
+
+/**
+ * Utility class identifying a BGP table type. A table type is formed by two identifiers: AFI and SAFI.
+ */
+public final class BGPTableType implements Comparable<BGPTableType>, Identifier {
+
+       private static final long serialVersionUID = -5502662876916458740L;
+
+       private final BGPSubsequentAddressFamily safi;
+
+       private final BGPAddressFamily afi;
+
+       /**
+        * Creates BGP Table type.
+        * 
+        * @param afi Address Family Identifier
+        * @param safi Subsequent Address Family Identifier
+        */
+       public BGPTableType(final BGPAddressFamily afi, final BGPSubsequentAddressFamily safi) {
+               this.afi = Preconditions.checkNotNull(afi, "Address family may not be null");
+               this.safi = Preconditions.checkNotNull(safi, "Subsequent address family may not be null");
+       }
+
+       /**
+        * Returns Address Family Identifier.
+        * 
+        * @return afi AFI
+        */
+       public BGPAddressFamily getAddressFamily() {
+               return this.afi;
+       }
+
+       /**
+        * Returns Subsequent Address Family Identifier.
+        * 
+        * @return safi SAFI
+        */
+       public BGPSubsequentAddressFamily getSubsequentAddressFamily() {
+               return this.safi;
+       }
+
+       @Override
+       public int hashCode() {
+               int ret = 3 * this.afi.hashCode();
+               ret += this.safi.hashCode();
+               return ret;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (obj != null && obj instanceof BGPTableType) {
+                       final BGPTableType o = (BGPTableType) obj;
+                       return this.afi.equals(o.afi) && this.safi.equals(o.safi);
+               }
+               return false;
+       }
+
+       @Override
+       public int compareTo(final BGPTableType other) {
+               if (other == null)
+                       return 1;
+
+               final int c = this.afi.compareTo(other.afi);
+               if (c != 0)
+                       return c;
+               return this.safi.compareTo(other.safi);
+       }
+
+       @Override
+       public String toString() {
+               return this.afi.toString() + "." + this.safi.toString();
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BaseBGPObjectState.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/BaseBGPObjectState.java
new file mode 100644 (file)
index 0000000..5762eb5
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import org.opendaylight.protocol.concepts.State;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * 
+ * A common interface for objects that can be added to a topology. It can be either BGPRoute, BGPLink, BGPNode or
+ * BGPPrefix.
+ * 
+ */
+public class BaseBGPObjectState implements State {
+
+       private static final long serialVersionUID = 2371691093534458869L;
+
+       private final BGPOrigin origin;
+       private final BGPAggregator aggregator;
+
+       /**
+        * Creates BaswBGPObjectState.
+        * 
+        * @param origin {@link BGPOrigin}
+        * @param aggregator {@link BGPAggregator}
+        */
+       public BaseBGPObjectState(final BGPOrigin origin, final BGPAggregator aggregator) {
+               super();
+               this.origin = origin;
+               this.aggregator = aggregator;
+       }
+
+       protected BaseBGPObjectState(final BaseBGPObjectState orig) {
+               super();
+               this.origin = orig.origin;
+               this.aggregator = orig.aggregator;
+       }
+
+       /**
+        * 
+        * @return the value of the ORIGIN attribute
+        */
+       public final BGPOrigin getOrigin() {
+               return this.origin;
+       }
+
+       /**
+        * 
+        * @return BGPAggregator attribute of this object
+        */
+       public final BGPAggregator getAggregator() {
+               return this.aggregator;
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("aggregator", this.aggregator);
+               toStringHelper.add("origin", this.origin);
+               return toStringHelper;
+       }
+
+       protected BaseBGPObjectState newInstance() {
+               return new BaseBGPObjectState(this);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.aggregator == null) ? 0 : this.aggregator.hashCode());
+               result = prime * result + ((this.origin == null) ? 0 : this.origin.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final BaseBGPObjectState other = (BaseBGPObjectState) obj;
+               if (this.aggregator == null) {
+                       if (other.aggregator != null)
+                               return false;
+               } else if (!this.aggregator.equals(other.aggregator))
+                       return false;
+               if (this.origin != other.origin)
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ClusterIdentifier.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ClusterIdentifier.java
new file mode 100644 (file)
index 0000000..b28b05d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class representing a BGP route-reflector cluster identifier.
+ */
+public final class ClusterIdentifier extends AbstractIdentifier<ClusterIdentifier> {
+       private static final long serialVersionUID = 7119651900750614105L;
+       /**
+        * Size of cluster identifier in bytes.
+        */
+       public static final int SIZE = 4;
+       private final byte[] clusterId;
+
+       /**
+        * Initialize a new Cluster Identifier.
+        * 
+        * @param clusterId 4-byte identifier
+        * @throws IllegalArgumentException if the length of supplied clusterId is not 6 bytes
+        */
+       public ClusterIdentifier(final byte[] clusterId) {
+               Preconditions.checkArgument(clusterId.length == 4, "Invalid Cluster ID");
+               this.clusterId = clusterId;
+       }
+
+       @Override
+       public byte[] getBytes() {
+               return this.clusterId;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("clusterId", ByteArray.toHexString(clusterId, "."));
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/Community.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/Community.java
new file mode 100644 (file)
index 0000000..b8ce214
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import java.io.Serializable;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.base.Preconditions;
+
+/**
+ * Object representation of a RFC1997 Community tag. Communities are a way for the advertising entitiy to attach
+ * semantic meaning/policy to advertised objects.
+ */
+public final class Community implements Serializable {
+       /**
+        * NO_EXPORT community. All routes received carrying a communities attribute containing this value MUST NOT be
+        * advertised outside a BGP confederation boundary (a stand-alone autonomous system that is not part of a
+        * confederation should be considered a confederation itself).
+        */
+       public static final Community NO_EXPORT = new Community(new ASNumber(0xFFFF), 0xFF01);
+       /**
+        * NO_ADVERTISE community. All routes received carrying a communities attribute containing this value MUST NOT be
+        * advertised to other BGP peers.
+        */
+       public static final Community NO_ADVERTISE = new Community(new ASNumber(0xFFFF), 0xFF02);
+       /**
+        * NO_EXPORT_SUBCONFED community. All routes received carrying a communities attribute containing this value MUST
+        * NOT be advertised to external BGP peers (this includes peers in other members autonomous systems inside a BGP
+        * confederation).
+        */
+       public static final Community NO_EXPORT_SUBCONFED = new Community(new ASNumber(0xFFFF), 0xFF03);
+
+       private static final long serialVersionUID = -944853598551415685L;
+
+       private final int semantics;
+
+       private final ASNumber as;
+
+       /**
+        * Create a new community tag for a particular AS number and semantics.
+        * 
+        * @param as Global semantics namespace identifier (usually the tagging Autonomous System)
+        * @param semantics Sematics identifier (specific meaning defined externally by the namespace)
+        */
+       public Community(final ASNumber as, final int semantics) {
+               Preconditions.checkArgument(as.getHighValue() == 0, "Invalid AS number specified");
+               Preconditions.checkArgument(semantics > 0 && semantics < 65535, "Invalid semantics specified");
+               this.semantics = semantics;
+               this.as = as;
+       }
+
+       /**
+        * Return semantics attribute of community.
+        * 
+        * @return Semantics attribute
+        */
+       public int getSemantics() {
+               return this.semantics;
+       }
+
+       /**
+        * Return ASNumber of community.
+        * 
+        * @return {@link ASNumber}
+        */
+       public ASNumber getAs() {
+               return this.as;
+       }
+
+       @Override
+       public boolean equals(final Object o) {
+               if (!(o instanceof Community))
+                       return false;
+
+               final Community c = (Community) o;
+               return this.as.equals(c.as) && this.semantics == c.semantics;
+       }
+
+       @Override
+       public int hashCode() {
+               return 7 * this.as.hashCode() + 13 * this.semantics;
+       }
+
+       @Override
+       public final String toString() {
+               final StringBuilder sb = new StringBuilder(this.as.toString());
+               sb.append(':');
+               sb.append(this.semantics);
+               return sb.toString();
+       }
+
+       /**
+        * Creates a Community from its String representation.
+        * 
+        * @param string String representation of a community
+        * @return new Community
+        */
+       public static Community valueOf(final String string) {
+               final String[] parts = string.split(":", 2);
+
+               final int asn = Integer.valueOf(parts[0]);
+               final int sem = Integer.valueOf(parts[1]);
+               return new Community(new ASNumber(0, asn), sem);
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ExtendedCommunity.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/ExtendedCommunity.java
new file mode 100644 (file)
index 0000000..feb4bf7
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import java.io.Serializable;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Object representation of basic Extended Community, as defined by RFC4360. Extended communities are semantic tags,
+ * pretty much same way communities defined in RFC1997, with the notable exceptions of supporting four-byte AS numbers
+ * and having a more complicated structure.
+ */
+public abstract class ExtendedCommunity implements Serializable {
+
+       private static final long serialVersionUID = -6279624143516991855L;
+       private final boolean ianaAuthority;
+       private final boolean transitive;
+
+       /**
+        * Initialize the base class with specified authority/transitive bits.
+        * 
+        * @param ianaAuthority Value of the 'IANA Authority' bit
+        * @param transitive Value of the 'Transitive' bit
+        */
+       protected ExtendedCommunity(final boolean ianaAuthority, final boolean transitive) {
+               this.ianaAuthority = ianaAuthority;
+               this.transitive = transitive;
+       }
+
+       /**
+        * Check what authority IANA holds over this extended community.
+        * 
+        * @return <li>false IANA-assignable type using the "First Come First Serve" policy
+        * 
+        *         <li>true Part of this Type Field space is for IANA assignable types using either the Standard Action or
+        *         the Early IANA Allocation policy. The rest of this Type Field space is for Experimental use.
+        */
+       public final boolean getIanaAuthority() {
+               return this.ianaAuthority;
+       }
+
+       /**
+        * Check if a community is transitive.
+        * 
+        * @return <li>true: the community is transitive <li>false: the community is not transitive
+        */
+       public final boolean isTransitive() {
+               return this.transitive;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (this.ianaAuthority ? 1231 : 1237);
+               result = prime * result + (this.transitive ? 1231 : 1237);
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof ExtendedCommunity))
+                       return false;
+               final ExtendedCommunity other = (ExtendedCommunity) obj;
+               if (this.ianaAuthority != other.ianaAuthority)
+                       return false;
+               if (this.transitive != other.transitive)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("ianaAuthority", ianaAuthority);
+               toStringHelper.add("transitive", transitive);
+               return toStringHelper;
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/IPv4NextHop.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/IPv4NextHop.java
new file mode 100644 (file)
index 0000000..e5c8726
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * DTO for a subtype of Next Hop, containing type IPv4 addresses.
+ */
+public final class IPv4NextHop extends AbstractNextHop<IPv4Address> {
+       private static final long serialVersionUID = -7013857868462257974L;
+
+       /**
+        * Construct a new IPv4-based next hop.
+        * 
+        * @param global {@link IPv4Address}
+        */
+       public IPv4NextHop(final IPv4Address global) {
+               super(global, null);
+       }
+
+       /**
+        * Creates a new IPv4NextHop using string IPv4Address.
+        * 
+        * @param string String representation of IPv4Address.
+        * @return new IPv4NextHop
+        */
+       public static IPv4NextHop forString(final String string) {
+               return new IPv4NextHop(IPv4.FAMILY.addressForString(string));
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/IPv6NextHop.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/IPv6NextHop.java
new file mode 100644 (file)
index 0000000..6ccdd2f
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+
+/**
+ * DTO for a subtype of NextHop, containing type IPv6 addresses.
+ */
+public final class IPv6NextHop extends AbstractNextHop<IPv6Address> {
+       private static final long serialVersionUID = -6656906151774744248L;
+
+       /**
+        * Construct a new IPv6 nexhop with only a global address.
+        * 
+        * @param global Globally-visible address
+        */
+       public IPv6NextHop(final IPv6Address global) {
+               this(global, null);
+       }
+
+       /**
+        * Construct a new IPv6 nexhop with both global and link-local address.
+        * 
+        * @param global Globally-visible address
+        * @param linkLocal Link-local address
+        */
+       public IPv6NextHop(final IPv6Address global, final IPv6Address linkLocal) {
+               super(global, linkLocal);
+       }
+
+       /**
+        * Creates a new IPv6NextHop using string IPv6Address.
+        * 
+        * @param global String representation of global IPv6Address.
+        * @return new IPv6NextHop
+        */
+       public static IPv6NextHop forString(final String global) {
+               return new IPv6NextHop(IPv6.FAMILY.addressForString(global));
+       }
+
+       /**
+        * Creates a new IPv6NextHop using global and linkLocal string IPv6Addresses.
+        * 
+        * @param global String representation of global IPv6Address
+        * @param linklocal String representation of linkLocal IPv6Address
+        * @return new IPv6NextHop
+        */
+       public static IPv6NextHop forString(final String global, final String linkLocal) {
+               return new IPv6NextHop(IPv6.FAMILY.addressForString(global), IPv6.FAMILY.addressForString(linkLocal));
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/Inet4SpecificExtendedCommunity.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/Inet4SpecificExtendedCommunity.java
new file mode 100644 (file)
index 0000000..9b281e1
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class representing a <a href="http://tools.ietf.org/html/rfc4360#section-3.2">IPv4 Address Specific Extended
+ * Community</a>.
+ */
+public class Inet4SpecificExtendedCommunity extends ExtendedCommunity implements Serializable {
+
+       private static final long serialVersionUID = 1355924956883963072L;
+       private final IPv4Address globalAdmin;
+       private final byte[] localAdmin;
+       private final int subType;
+
+       /**
+        * Create a new IPv4 address-specific extended community.
+        * 
+        * @param transitive True if the community is transitive
+        * @param subType Community subtype, has to be in range 0-255
+        * @param globalAdmin Globally-assigned namespace (IPv4 address)
+        * @param localAdmin byte[] Locally-assigned value, has to be 2 bytes long
+        * @throws IllegalArgumentException when either subtype or localAdmin is invalid
+        */
+       public Inet4SpecificExtendedCommunity(final boolean transitive, final int subType, final IPv4Address globalAdmin,
+                       final byte[] localAdmin) {
+               super(false, transitive);
+               Preconditions.checkArgument(subType > 0 && subType < 255, "Invalid Sub-Type " + subType);
+               Preconditions.checkArgument(localAdmin.length == 2, "Invalid Local Administrator");
+               this.subType = subType;
+               this.globalAdmin = Preconditions.checkNotNull(globalAdmin);
+               this.localAdmin = localAdmin;
+       }
+
+       /**
+        * Returns the community subtype.
+        * 
+        * @return Community subtype
+        */
+       public final int getSubType() {
+               return this.subType;
+       }
+
+       /**
+        * Returns the globally-assigned namespace.
+        * 
+        * @return Globally-assigned namespace
+        */
+       public final IPv4Address getGlobalAdmin() {
+               return this.globalAdmin;
+       }
+
+       /**
+        * Returns the locally-assigned community value.
+        * 
+        * @return Locally-assigned community value
+        */
+       public final byte[] getLocalAdmin() {
+               return this.localAdmin;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("subType", this.subType);
+               toStringHelper.add("globalAdmin", this.globalAdmin);
+               toStringHelper.add("localAdmin", this.localAdmin);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.globalAdmin == null) ? 0 : this.globalAdmin.hashCode());
+               result = prime * result + Arrays.hashCode(this.localAdmin);
+               result = prime * result + this.subType;
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final Inet4SpecificExtendedCommunity other = (Inet4SpecificExtendedCommunity) obj;
+               if (this.globalAdmin == null) {
+                       if (other.globalAdmin != null)
+                               return false;
+               } else if (!this.globalAdmin.equals(other.globalAdmin))
+                       return false;
+               if (!Arrays.equals(this.localAdmin, other.localAdmin))
+                       return false;
+               if (this.subType != other.subType)
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/NextHop.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/NextHop.java
new file mode 100644 (file)
index 0000000..97c3a81
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import java.io.Serializable;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * Interface for BGP Next Hop Attribute.
+ * @see <a  href="http://tools.ietf.org/html/rfc2545#section-3">Next Hop</a>
+ *
+ * @param <T> subtype of Network Address
+ */
+public interface NextHop<T extends NetworkAddress<?>> extends Serializable {
+       /**
+        * Return the global address of the next hop. This operation is
+        * always applicable.
+        *
+        * @return T global address
+        */
+       public T getGlobal();
+
+       /**
+        * Return the link-local address of the next hop. This operation is
+        * applicable only to some address types. For address types where
+        * it not applicable, null is returned.
+        *
+        * @return T link-local address, null if unsupported
+        */
+       public T getLinkLocal();
+}
+
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/OpaqueExtendedCommunity.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/OpaqueExtendedCommunity.java
new file mode 100644 (file)
index 0000000..57556dd
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import java.io.Serializable;
+
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class representing a <a href="http://tools.ietf.org/html/rfc4360#section-3.3">Opaque Extended Community</a>.
+ */
+public class OpaqueExtendedCommunity extends ExtendedCommunity implements Serializable {
+
+       private static final long serialVersionUID = 2675224758578219774L;
+       private final byte[] value;
+       private final int subType;
+
+       /**
+        * Create a new opaque extended community.
+        * 
+        * @param transitive True if the community is transitive
+        * @param subType Community subtype, has to be in range 0-255
+        * @param value Community value, has to be 6 bytes long
+        * @throws IllegalArgumentException when either subtype or value are invalid
+        */
+       public OpaqueExtendedCommunity(final boolean transitive, final int subType, final byte[] value) {
+               super(false, transitive);
+               Preconditions.checkArgument(subType > 0 && subType < 255, "Invalid Sub-Type");
+               Preconditions.checkArgument(value.length == 6, "Invalid value");
+               this.subType = subType;
+               this.value = value;
+       }
+
+       /**
+        * Returns community subtype.
+        * 
+        * @return Community subtype
+        */
+       public final int getSubType() {
+               return this.subType;
+       }
+
+       /**
+        * Returns community value
+        * 
+        * @return Community value
+        */
+       public final byte[] getValue() {
+               return this.value;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("subType", this.subType);
+               toStringHelper.add("value", this.value);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/RouteOriginCommunity.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/RouteOriginCommunity.java
new file mode 100644 (file)
index 0000000..9868b3f
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.concepts;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * @see <a  href="http://tools.ietf.org/html/rfc4360#section-5">Route Origin Community</a>
+ */
+public class RouteOriginCommunity extends ASSpecificExtendedCommunity {
+
+       private static final long serialVersionUID = 540725495203637583L;
+
+       /**
+        * Construct a RouteOriginCommunity based on global and local
+        * administrator values.
+        *
+        * @param globalAdmin Global administrator (AS number)
+        * @param localAdmin Local administrator (AS-specific, opaque value)
+        */
+       public RouteOriginCommunity(final ASNumber globalAdmin, final byte[] localAdmin) {
+               super(false, 3, globalAdmin, localAdmin);
+       }
+}
+
diff --git a/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/RouteTargetCommunity.java b/bgp/concepts/src/main/java/org/opendaylight/protocol/bgp/concepts/RouteTargetCommunity.java
new file mode 100644 (file)
index 0000000..340fe1f
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * @see <a href="http://tools.ietf.org/html/rfc4360#section-4">Route Target Community</a>
+ */
+public class RouteTargetCommunity extends ASSpecificExtendedCommunity {
+
+       private static final long serialVersionUID = 855252238770644603L;
+
+       /**
+        * 
+        * @param globalAdmin Globally-administered identifier, i.e. an {@link ASNumber}
+        * @param localAdmin Locally-administered identifier
+        */
+       public RouteTargetCommunity(final ASNumber globalAdmin, final byte[] localAdmin) {
+               super(false, 2, globalAdmin, localAdmin);
+       }
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/ASPathTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/ASPathTest.java
new file mode 100644 (file)
index 0000000..eb39c75
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public class ASPathTest {
+
+       private ASNumber asn1, asn2, asn3, asn4, asn5, asn6, asn7, asn8;
+
+       private List<ASNumber> visibleAsPath;
+       private Set<ASNumber> aggregatedAsPath;
+
+       @Before
+       public void init() {
+               asn1 = new ASNumber(100, 200);
+               asn2 = new ASNumber(65534);
+               asn3 = new ASNumber(0, 200);
+               asn4 = new ASNumber(100, 199);
+               asn5 = new ASNumber(99, 199);
+               asn6 = new ASNumber(64538);
+               asn7 = new ASNumber(0, 200);
+               asn8 = new ASNumber(100, 0);
+
+               visibleAsPath = new ArrayList<ASNumber>();
+               aggregatedAsPath = new HashSet<ASNumber>();
+
+               visibleAsPath.add(asn1);
+               visibleAsPath.add(asn2);
+               visibleAsPath.add(asn3);
+               visibleAsPath.add(asn4);
+
+               aggregatedAsPath.add(asn5);
+               aggregatedAsPath.add(asn6);
+               aggregatedAsPath.add(asn7);
+               aggregatedAsPath.add(asn8);
+       }
+
+       @Test
+       public void testGetXXXPath() {
+               ASPath asp1 = ASPath.EMPTY;
+               assertEquals(0, asp1.getVisibleAsPath().size());
+               assertEquals(0, asp1.getAggregatedAsPath().size());
+
+               ASPath asp2 = new ASPath(visibleAsPath);
+               assertEquals(4, asp2.getVisibleAsPath().size());
+               assertEquals(0, asp2.getAggregatedAsPath().size());
+
+               ASPath asp3 = new ASPath(visibleAsPath, aggregatedAsPath);
+               assertEquals(4, asp3.getVisibleAsPath().size());
+               assertEquals(4, asp3.getAggregatedAsPath().size());
+       }
+
+       @Test
+       public void testEqualsHashCode() {
+               ASPath asp1 = ASPath.EMPTY;
+               ASPath asp2 = asp1;
+               assertEquals(asp1, asp2);
+               assertEquals(asp1.hashCode(), asp2.hashCode());
+               assertNotNull(asp1);
+               assertThat(asp1, not(new Object()));
+
+               ASPath asp3 = new ASPath(visibleAsPath, aggregatedAsPath);
+               assertThat(asp1, not(equalTo(asp3)));
+               assertThat(asp1.hashCode(), not(equalTo(asp3.hashCode())));
+
+               ASPath asp4 = new ASPath(new ArrayList<ASNumber>(), aggregatedAsPath);
+               assertThat(asp3, not(equalTo(asp4)));
+       }
+
+       @Test
+       public void testToString() {
+               ASPath asp = new ASPath(visibleAsPath, aggregatedAsPath);
+               assertNotNull(asp.toString());
+       }
+
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/ASSpecificExtendedCommunityTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/ASSpecificExtendedCommunityTest.java
new file mode 100644 (file)
index 0000000..6693692
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ASSpecificExtendedCommunity;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public class ASSpecificExtendedCommunityTest {
+
+       private final boolean transitive = true;
+       private final int subType = 123;
+       private final ASNumber globalAdmin = new ASNumber(100, 200);
+       private final byte[] localAdmin = new byte[] { 10, 0, 0, 1 };
+
+       @Test
+       public void testOverflows() {
+               try {
+                       new ASSpecificExtendedCommunity(this.transitive, -2, this.globalAdmin, this.localAdmin);
+                       fail("Sub-type is negative!");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid Sub-Type", e.getMessage());
+               }
+               try {
+                       new ASSpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, new byte[] {});
+                       fail("Local Administrator has illegal length!");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid Local Administrator", e.getMessage());
+               }
+       }
+
+       @Test
+       public void testGetSubType() {
+               final ASSpecificExtendedCommunity asSpecExCom = new ASSpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, this.localAdmin);
+               assertEquals(123, asSpecExCom.getSubType());
+               assertEquals(new ASNumber(100, 200), asSpecExCom.getGlobalAdmin());
+               assertArrayEquals(new byte[] { 10, 0, 0, 1 }, asSpecExCom.getLocalAdmin());
+
+               final ASSpecificExtendedCommunity a1 = new ASSpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, this.localAdmin);
+               assertEquals(a1.toString(), asSpecExCom.toString());
+       }
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/ClusterIdentifierTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/ClusterIdentifierTest.java
new file mode 100644 (file)
index 0000000..4272a86
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ClusterIdentifier;
+
+public class ClusterIdentifierTest {
+
+       @Test
+       public void testClusterIdentifier() {
+               final ClusterIdentifier id = new ClusterIdentifier(new byte[] { 13, 14, 15, 16 });
+               try {
+                       new ClusterIdentifier(new byte[] { 5, 6 });
+                       fail("Cluster ID is invalid!");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid Cluster ID", e.getMessage());
+               }
+
+               final ClusterIdentifier id1 = new ClusterIdentifier(new byte[] { 13, 14, 15, 16 });
+
+               assertEquals(id1.toString(), id.toString());
+
+               assertArrayEquals(id1.getBytes(), new byte[] { 13, 14, 15, 16 });
+       }
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/CommunityTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/CommunityTest.java
new file mode 100644 (file)
index 0000000..54f099f
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.OpaqueExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.RouteOriginCommunity;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public class CommunityTest {
+
+       @Test
+       public void testCommunity() {
+               new Community(new ASNumber(0, 10), 222);
+               final ASNumber as = new ASNumber(12);
+               final Community c = new Community(as, 12);
+               assertEquals(as, c.getAs());
+               assertEquals(12, c.getSemantics());
+       }
+
+       @Test
+       public void testOverflows() {
+               try {
+                       new Community(new ASNumber(0, 10), -2);
+                       fail("Semantics under range.");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid semantics specified", e.getMessage());
+               }
+               try {
+                       new Community(new ASNumber(5, 10), 5);
+                       fail("AS high number cannot be null");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid AS number specified", e.getMessage());
+               }
+               try {
+                       new Community(new ASNumber(0, 10), 65536);
+                       fail("Semantics above range.");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid semantics specified", e.getMessage());
+               }
+       }
+
+       @Test
+       public void testEquals() {
+               final Community c1 = new Community(new ASNumber(0, 10), 222);
+               final Community c2 = new Community(new ASNumber(0, 10), 222);
+               assertEquals(c1, c2);
+               assertThat(c1, not(new Object()));
+       }
+
+       @Test
+       public void testHashCode() {
+               final Community c1 = new Community(new ASNumber(0, 10), 222);
+               final Community c2 = new Community(new ASNumber(0, 10), 222);
+               assertEquals(c1.hashCode(), c2.hashCode());
+       }
+
+       @Test
+       public void testToString() {
+               final Community c = new Community(new ASNumber(0, 10), 222);
+               assertNotNull(c.toString());
+       }
+
+       @Test
+       public void testValueOf() {
+               final Community comm = Community.valueOf("12:50");
+               assertEquals(comm, new Community(new ASNumber(0, 12), 50));
+       }
+
+       @Test
+       public void testExtendedCommunity() {
+               final ExtendedCommunity ec = new OpaqueExtendedCommunity(false, 5, new byte[] { 1, 2, 3, 4, 5, 6 });
+               final Object ec2 = new RouteOriginCommunity(new ASNumber(84), new byte[] { 1, 2, 3, 4 });
+               assertNotSame(ec, ec2);
+               assertEquals(ec, new OpaqueExtendedCommunity(false, 5, new byte[] { 1, 2, 3, 4, 5, 6 }));
+               assertEquals(ec.hashCode(), (new OpaqueExtendedCommunity(false, 5, new byte[] { 1, 2, 3, 4, 5, 6 })).hashCode());
+       }
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/IPv4NextHopTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/IPv4NextHopTest.java
new file mode 100644 (file)
index 0000000..13357f5
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+public class IPv4NextHopTest {
+
+       private IPv4NextHop nextHop;
+
+       @Before
+       public void init() {
+               final IPv4Address address = IPv4.FAMILY.addressForString("10.0.0.1");
+               this.nextHop = new IPv4NextHop(address);
+       }
+
+       @Test
+       public void testGetGlobal() {
+               final IPv4Address address = IPv4.FAMILY.addressForString("10.0.0.1");
+               assertEquals(address, this.nextHop.getGlobal());
+       }
+
+       @Test
+       public void testGetLinkLocal() {
+               assertNull(this.nextHop.getLinkLocal());
+       }
+
+       @Test
+       public void testHashCode() {
+               final IPv4NextHop nextHop2 = IPv4NextHop.forString("10.0.0.1");
+               assertEquals(this.nextHop.hashCode(), nextHop2.hashCode());
+       }
+
+       @Test
+       public void testEquals() {
+               assertNotNull(this.nextHop);
+               assertThat(this.nextHop, not(new Object()));
+
+               final IPv4NextHop nextHop1 = this.nextHop;
+               assertEquals(this.nextHop, nextHop1);
+
+               final IPv4NextHop nextHop2 = IPv4NextHop.forString("10.0.0.1");
+               assertEquals(this.nextHop, nextHop2);
+       }
+
+       @Test
+       public void testToString() {
+               assertNotNull(this.nextHop.toString());
+       }
+
+       @Test
+       public void testForString() {
+               assertEquals(this.nextHop, IPv4NextHop.forString("10.0.0.1"));
+       }
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/IPv6NextHopTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/IPv6NextHopTest.java
new file mode 100644 (file)
index 0000000..14117a9
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+
+public class IPv6NextHopTest {
+
+       private IPv6NextHop nextHopA;
+       private IPv6NextHop nextHopB;
+
+       @Before
+       public void init() {
+               final IPv6Address global = IPv6.FAMILY.addressForString("2001:db8:85a3:0:0:8a2e:370:7331");
+               final IPv6Address local = IPv6.FAMILY.addressForString("2001:db8:85a3:0:0:8a2e:370:0000");
+               this.nextHopA = new IPv6NextHop(global);
+               this.nextHopB = new IPv6NextHop(global, local);
+       }
+
+       @Test
+       public void testGetGlobal() {
+               final IPv6Address globalTestAddress = IPv6.FAMILY.addressForString("2001:db8:85a3:0:0:8a2e:370:7331");
+
+               assertEquals(this.nextHopA.getGlobal(), globalTestAddress);
+               assertEquals(this.nextHopB.getGlobal(), globalTestAddress);
+       }
+
+       @Test
+       public void testGetLinkLocal() {
+               final IPv6Address localTestAddress = IPv6.FAMILY.addressForString("2001:db8:85a3:0:0:8a2e:370:0000");
+
+               assertNull(this.nextHopA.getLinkLocal());
+               assertEquals(this.nextHopB.getLinkLocal(), localTestAddress);
+       }
+
+       @Test
+       public void testHashCode() {
+               final IPv6NextHop nextHop1 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331");
+               final IPv6NextHop nextHop2 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331", "2001:db8:85a3:0:0:8a2e:370:0000");
+               assertEquals(this.nextHopA.hashCode(), nextHop1.hashCode());
+               assertEquals(this.nextHopB.hashCode(), nextHop2.hashCode());
+       }
+
+       @Test
+       public void testEquals() {
+               assertNotNull(this.nextHopA);
+               assertNotNull(this.nextHopB);
+               assertThat(this.nextHopA, not(new Object()));
+               assertThat(this.nextHopB, not(new Object()));
+
+               final IPv6NextHop nextHop1 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331");
+               final IPv6NextHop nextHop2 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331", "2001:db8:85a3:0:0:8a2e:370:0000");
+               assertEquals(this.nextHopA, nextHop1);
+               assertEquals(this.nextHopB, nextHop2);
+
+               final IPv6NextHop x = this.nextHopA;
+               assertEquals(this.nextHopA, x);
+
+               final IPv6NextHop y = this.nextHopB;
+               assertEquals(this.nextHopB, y);
+
+               final IPv6NextHop nextHop3 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7332");
+               final IPv6NextHop nextHop4 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7332", "2001:db8:85a3:0:0:8a2e:370:0000");
+               assertThat(this.nextHopA, not(nextHop3));
+               assertThat(this.nextHopA, not(nextHop4));
+               assertThat(this.nextHopB, not(nextHop3));
+               assertThat(this.nextHopB, not(nextHop4));
+       }
+
+       @Test
+       public void testToString() {
+               assertNotNull(this.nextHopA.toString());
+               assertNotNull(this.nextHopB.toString());
+       }
+
+       @Test
+       public void testForString() {
+               assertEquals(this.nextHopA, IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331"));
+               assertEquals(this.nextHopB, IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331", "2001:db8:85a3:0:0:8a2e:370:0000"));
+       }
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/Inet4SpecificExtendedCommunityTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/Inet4SpecificExtendedCommunityTest.java
new file mode 100644 (file)
index 0000000..918d85d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.Inet4SpecificExtendedCommunity;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+public class Inet4SpecificExtendedCommunityTest {
+
+       private boolean transitive;
+       private int subType;
+       private IPv4Address globalAdmin;
+       private byte[] localAdmin;
+
+       private Inet4SpecificExtendedCommunity community;
+
+       @Before
+       public void init() {
+               this.transitive = true;
+               this.subType = 123;
+               this.globalAdmin = IPv4.FAMILY.addressForString("10.0.0.1");
+               this.localAdmin = new byte[] { 10, 1 };
+               this.community = new Inet4SpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, this.localAdmin);
+       }
+
+       @Test
+       public void testOverflows() {
+               try {
+                       new Inet4SpecificExtendedCommunity(this.transitive, -2, this.globalAdmin, this.localAdmin);
+                       fail("Sub-type is negative!");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid Sub-Type -2", e.getMessage());
+               }
+               try {
+                       new Inet4SpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, new byte[] { 10, 0, 1 });
+                       fail("Invalid length of local administrator!");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid Local Administrator", e.getMessage());
+               }
+               try {
+                       new Inet4SpecificExtendedCommunity(this.transitive, 256, this.globalAdmin, this.localAdmin);
+                       fail("Sub-type is above range!");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid Sub-Type 256", e.getMessage());
+               }
+       }
+
+       @Test
+       public void testGetSubType() {
+               final int subType = 123;
+               assertEquals(subType, this.community.getSubType());
+       }
+
+       @Test
+       public void testGetGlobalAdmin() {
+               final IPv4Address globalAdmin = IPv4.FAMILY.addressForString("10.0.0.1");
+               assertEquals(globalAdmin, this.community.getGlobalAdmin());
+       }
+
+       @Test
+       public void testGetLocalAdmin() {
+               final byte[] localAdmin = new byte[] { 10, 1 };
+               assertArrayEquals(localAdmin, this.community.getLocalAdmin());
+       }
+
+       @Test
+       public void testGetIanaAuthority() {
+               // Should be always false for Inet4SpecificExtendedCommunity instances
+               assertFalse(this.community.getIanaAuthority());
+       }
+
+       @Test
+       public void testIsTransitive() {
+               assertTrue(this.community.isTransitive());
+       }
+
+       @Test
+       public void testToString() {
+               final Inet4SpecificExtendedCommunity comm = new Inet4SpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, this.localAdmin);
+               assertEquals(this.community.toString(), comm.toString());
+               assertEquals(this.community, comm);
+               assertEquals(this.community.hashCode(), comm.hashCode());
+       }
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/OpaqueExtendedCommunityTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/OpaqueExtendedCommunityTest.java
new file mode 100644 (file)
index 0000000..c09aeb8
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.OpaqueExtendedCommunity;
+
+public class OpaqueExtendedCommunityTest {
+
+       private boolean transitive;
+       private int subType;
+       private byte[] value;
+
+       private OpaqueExtendedCommunity community;
+
+       @Before
+       public void init() {
+               this.transitive = true;
+               this.subType = 222;
+               this.value = new byte[] { 1, 5, 9, 3, 5, 7 };
+               this.community = new OpaqueExtendedCommunity(this.transitive, this.subType, this.value);
+       }
+
+       @Test
+       public void testOverflows() {
+               try {
+                       new OpaqueExtendedCommunity(this.transitive, -2, this.value);
+                       fail("Sub-type is negative!");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid Sub-Type", e.getMessage());
+               }
+               try {
+                       new OpaqueExtendedCommunity(this.transitive, 256, this.value);
+                       fail("Sub-type is above range!");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid Sub-Type", e.getMessage());
+               }
+               try {
+                       new OpaqueExtendedCommunity(this.transitive, this.subType, new byte[] { 0, 1, 2, 3, 4, 5, 6, });
+                       fail("Constructor successful unexpectedly");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Invalid value", e.getMessage());
+               }
+       }
+
+       @Test
+       public void testGetSubType() {
+               assertEquals(222, this.community.getSubType());
+       }
+
+       @Test
+       public void testGetValue() {
+               assertArrayEquals(new byte[] { 1, 5, 9, 3, 5, 7 }, this.community.getValue());
+       }
+
+       @Test
+       public void testGetIanaAuthority() {
+               assertFalse(this.community.getIanaAuthority());
+       }
+
+       @Test
+       public void testIsTransitive() {
+               assertTrue(this.community.isTransitive());
+       }
+
+       @Test
+       public void testToString() {
+               final OpaqueExtendedCommunity c = new OpaqueExtendedCommunity(false, this.subType, this.value);
+               assertNotSame(c.toString(), this.community.toString());
+       }
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/RouteOriginCommunityTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/RouteOriginCommunityTest.java
new file mode 100644 (file)
index 0000000..8279e76
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.RouteOriginCommunity;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public class RouteOriginCommunityTest {
+
+       private RouteOriginCommunity community;
+
+       @Before
+       public void init() {
+               final ASNumber globalAdmin = new ASNumber(100, 200);
+               final byte[] localAdmin = new byte[] { 10, 0, 0, 1 };
+               this.community = new RouteOriginCommunity(globalAdmin, localAdmin);
+       }
+
+       @Test
+       public void testGetSubType() {
+               assertEquals(3, this.community.getSubType());
+       }
+
+       @Test
+       public void testGetGlobalAdmin() {
+               final ASNumber testAsn = new ASNumber(100, 200);
+               assertEquals(this.community.getGlobalAdmin(), testAsn);
+       }
+
+       @Test
+       public void testGetLocalAdmin() {
+               assertArrayEquals(new byte[] { 10, 0, 0, 1 }, this.community.getLocalAdmin());
+       }
+
+       @Test
+       public void testGetIanaAuthority() {
+               assertFalse(this.community.getIanaAuthority());
+       }
+
+       @Test
+       public void testIsTransitive() {
+               assertFalse(this.community.isTransitive());
+       }
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/RouteTargetCommunityTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/RouteTargetCommunityTest.java
new file mode 100644 (file)
index 0000000..1e29a6d
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.RouteTargetCommunity;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public class RouteTargetCommunityTest {
+
+       private RouteTargetCommunity community;
+
+       @Before
+       public void init() {
+               final ASNumber globalAdmin = new ASNumber(100, 200);
+               final byte[] localAdmin = new byte[] { 10, 0, 0, 1 };
+               this.community = new RouteTargetCommunity(globalAdmin, localAdmin);
+       }
+
+       @Test
+       public void testGetSubType() {
+               assertEquals(2, this.community.getSubType());
+       }
+
+       @Test
+       public void testGetGlobalAdmin() {
+               final ASNumber testAsn = new ASNumber(100, 200);
+               assertEquals(this.community.getGlobalAdmin(), testAsn);
+       }
+
+       @Test
+       public void testGetLocalAdmin() {
+               assertArrayEquals(new byte[] { 10, 0, 0, 1 }, this.community.getLocalAdmin());
+       }
+
+       @Test
+       public void testGetIanaAuthority() {
+               assertFalse(this.community.getIanaAuthority());
+       }
+
+       @Test
+       public void testIsTransitive() {
+               assertFalse(this.community.isTransitive());
+       }
+}
diff --git a/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/TableTypeTest.java b/bgp/concepts/src/test/java/org/opendaylight/protocol/bgp/concepts/TableTypeTest.java
new file mode 100644 (file)
index 0000000..388ae02
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.concepts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.IPv6;
+
+public class TableTypeTest {
+
+       @Test
+       public void testTableTypes() {
+               final BGPTableType tt1 = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.MPLSLabeledVPN);
+               final BGPTableType tt2 = new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.valueOf("MPLSLabeledVPN"));
+               final BGPTableType tt3 = new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.Unicast);
+
+               assertEquals(IPv6.FAMILY, BGPAddressFamily.IPv6.getAddressFamily());
+               assertNull(BGPAddressFamily.LinkState.getAddressFamily());
+
+               try {
+                       new BGPTableType(null, BGPSubsequentAddressFamily.MPLSLabeledVPN);
+                       fail("Null AFI!");
+               } catch (final NullPointerException e) {
+                       assertEquals("Address family may not be null", e.getMessage());
+               }
+
+               try {
+                       new BGPTableType(BGPAddressFamily.valueOf("IPv6"), null);
+                       fail("Null SAFI!");
+               } catch (final NullPointerException e) {
+                       assertEquals("Subsequent address family may not be null", e.getMessage());
+               }
+
+               assertFalse(tt1.equals(tt2));
+               assertNotSame(tt1.hashCode(), tt2.hashCode());
+               assertEquals(1, tt2.compareTo(tt1));
+               assertEquals(1, tt2.compareTo(tt3));
+               assertEquals(tt1.toString(), tt1.toString());
+               assertNotSame(tt1.getAddressFamily(), tt2.getAddressFamily());
+               assertEquals(tt1.getSubsequentAddressFamily(), tt2.getSubsequentAddressFamily());
+       }
+
+       @Test
+       public void testOrigin() {
+               final BGPOrigin or = BGPOrigin.EGP;
+               assertEquals(or.name(), "EGP");
+       }
+
+       @Test
+       public void testBaseBGPObjectState() {
+               final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.INCOMPLETE, null);
+               final BaseBGPObjectState state1 = new BaseBGPObjectState(BGPOrigin.INCOMPLETE, null);
+               assertNull(state.getAggregator());
+               assertEquals(BGPOrigin.INCOMPLETE, state.getOrigin());
+               assertEquals(state.toString(), state1.toString());
+
+               final BaseBGPObjectState s = new BaseBGPObjectState(state);
+               assertEquals(state, s);
+               assertEquals(state.hashCode(), s.hashCode());
+
+               assertEquals(s, s.newInstance());
+       }
+}
diff --git a/bgp/linkstate/.project b/bgp/linkstate/.project
new file mode 100644 (file)
index 0000000..21008d1
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>bgp-linkstate</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bgp/linkstate/pom.xml b/bgp/linkstate/pom.xml
new file mode 100644 (file)
index 0000000..48fa0a1
--- /dev/null
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>bgp-parent</artifactId>
+        <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-linkstate</artifactId>
+       <description>BGP linkstate concepts</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+    <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.code.findbugs</groupId>
+                       <artifactId>jsr305</artifactId>
+                       <version>2.0.1</version>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.bgp.linkstate
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>${checkstyle.version}</version>
+                               <configuration>
+                                       <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+                                       <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>BGP-CONCEPTS Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AbstractLANIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AbstractLANIdentifier.java
new file mode 100644 (file)
index 0000000..40e35d8
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractLANIdentifier<T extends RouterIdentifier> implements LANIdentifier<T> {
+       private static final long serialVersionUID = 1L;
+       private final T designatedRouter;
+
+       protected AbstractLANIdentifier(final T designatedRouter) {
+               this.designatedRouter = Preconditions.checkNotNull(designatedRouter);
+       }
+
+       @Override
+       final public T getDesignatedRouter() {
+               return this.designatedRouter;
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("designatedRouter", this.designatedRouter);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((designatedRouter == null) ? 0 : designatedRouter.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               AbstractLANIdentifier<?> other = (AbstractLANIdentifier<?>) obj;
+               if (designatedRouter == null) {
+                       if (other.designatedRouter != null)
+                               return false;
+               } else if (!designatedRouter.equals(other.designatedRouter))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AbstractNetworkAddressRouterIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AbstractNetworkAddressRouterIdentifier.java
new file mode 100644 (file)
index 0000000..49e04d5
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractNetworkAddressRouterIdentifier<T extends NetworkAddress<?>> implements NetworkAddressRouterIdentifier<T> {
+       private static final long serialVersionUID = 1L;
+       private final T address;
+
+       protected AbstractNetworkAddressRouterIdentifier(final T address) {
+               Preconditions.checkNotNull(address, "Address may not be null");
+               this.address = address;
+       }
+
+       @Override
+       public T getAddress() {
+               return this.address;
+       }
+
+       @Override
+       public final String toString() {
+               return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("address", this.address);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.address == null) ? 0 : this.address.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final AbstractNetworkAddressRouterIdentifier<?> other = (AbstractNetworkAddressRouterIdentifier<?>) obj;
+               if (this.address == null) {
+                       if (other.address != null)
+                               return false;
+               } else if (!this.address.equals(other.address))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AbstractOSPFLANIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AbstractOSPFLANIdentifier.java
new file mode 100644 (file)
index 0000000..26a0e2c
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * An abstract OSPF LAN "pseudonode" identifier. This class is specialized for OSPFv2 and OSPFv3 as the two differ only
+ * slightly in semantics.
+ */
+public abstract class AbstractOSPFLANIdentifier<T extends InterfaceIdentifier> extends AbstractLANIdentifier<OSPFRouterIdentifier> {
+       private static final long serialVersionUID = 1L;
+       private final T lanInterface;
+
+       protected AbstractOSPFLANIdentifier(final OSPFRouterIdentifier dr, final T lanInterface) {
+               super(dr);
+               this.lanInterface = Preconditions.checkNotNull(lanInterface);
+       }
+
+       public final T getLANInterface() {
+               return this.lanInterface;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("lanInterface", this.lanInterface);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((lanInterface == null) ? 0 : lanInterface.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               AbstractOSPFLANIdentifier<?> other = (AbstractOSPFLANIdentifier<?>) obj;
+               if (lanInterface == null) {
+                       if (other.lanInterface != null)
+                               return false;
+               } else if (!lanInterface.equals(other.lanInterface))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AdministrativeGroup.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AdministrativeGroup.java
new file mode 100644 (file)
index 0000000..8d773f7
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+/**
+ * Identifier class for Administrative Groups. Administrative groups, also
+ * known as Colors, are a way for administrative authority to assign objects
+ * to groups. This allows separation of policy, which defines what actions
+ * should be applied to a particular group from actual assignment of objects.
+ */
+public class AdministrativeGroup implements Comparable<AdministrativeGroup>, Identifier {
+       public static final AdministrativeGroup NONE = new AdministrativeGroup(0);
+       private static final long serialVersionUID = 6127162286553485280L;
+       private final long value;
+
+       /**
+        * Create a new administrative group. Each group has a numeric
+        * identifier in range 0-4294967295. Two groups with the same
+        * identifier are considered equal.
+        * 
+        * @param value Group identifier value
+        */
+       public AdministrativeGroup(final long value) {
+               if (value < 0 || value > 4294967295L)
+                       throw new IllegalArgumentException("Invalid Administrative Group value");
+               this.value = value;
+       }
+
+       /**
+        * Standard getter for value attribute of {@link AdministrativeGroup}.
+        *
+        * @return Group identifier value
+        */
+       public final long getValue() {
+               return value;
+       }
+
+       @Override
+       public final int compareTo(final AdministrativeGroup other) {
+               if (value < other.value)
+                       return -1;
+               if (value > other.value)
+                       return 1;
+               return 0;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (int) (value ^ (value >>> 32));
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof AdministrativeGroup))
+                       return false;
+               final AdministrativeGroup other = (AdministrativeGroup) obj;
+               if (value != other.value)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               return String.valueOf(value);
+       }
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AreaIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/AreaIdentifier.java
new file mode 100644 (file)
index 0000000..37677e6
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Area Identifier SubTLV from Identifier TLV.
+ * 
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-idr-ls-distribution-02#section-3.2.1.3">Area Identifier
+ *      SubTLV</a>
+ */
+public final class AreaIdentifier extends AbstractIdentifier<AreaIdentifier> {
+       private static final long serialVersionUID = 1L;
+       private final byte[] id;
+
+       /**
+        * Construct a new Node Area identifier. This constructor expects a non-empty byte array which is the are
+        * distinguisher. Maximum length of the array is capped at 20 bytes.
+        * 
+        * @param id Area identifier, expressed as a byte array
+        * @throws IllegalArgumentException if the identifier is not valid
+        */
+       public AreaIdentifier(final byte[] id) {
+               Preconditions.checkArgument(id.length == 4);
+               this.id = id;
+       }
+
+       /**
+        * Access the underlying identifier.
+        * 
+        * @return Identifier bytearray of AreaIdentifier.
+        */
+       @Override
+       public final byte[] getBytes() {
+               return this.id;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("id", ByteArray.toHexString(id, "."));
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/DomainIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/DomainIdentifier.java
new file mode 100644 (file)
index 0000000..8ccdee2
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Domain Identifier SubTLV from Identifier TLV.
+ * 
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-idr-ls-distribution-02#section-3.2.1.2">Domain Identifier
+ *      SubTLV</a>
+ */
+public final class DomainIdentifier extends AbstractIdentifier<DomainIdentifier> {
+
+       private static final long serialVersionUID = -5033319198070873474L;
+
+       private final byte[] id;
+
+       /**
+        * Create a new domain identifier using its raw identifier. There is not length constraint.
+        * 
+        * @param id Raw identifier, has to be four bytes long.
+        */
+       public DomainIdentifier(final byte[] id) {
+               Preconditions.checkNotNull(id);
+               Preconditions.checkArgument(id.length == 4);
+               this.id = id;
+       }
+
+       /**
+        * Returns the raw identifier
+        * 
+        * @return Raw identifier
+        */
+       @Override
+       public byte[] getBytes() {
+               return this.id;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("id", ByteArray.toHexString(id, "."));
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + Arrays.hashCode(this.id);
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final DomainIdentifier other = (DomainIdentifier) obj;
+               if (!Arrays.equals(this.id, other.id))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ExtendedRouteTag.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ExtendedRouteTag.java
new file mode 100644 (file)
index 0000000..0ec99e2
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.SignedBytes;
+
+public final class ExtendedRouteTag implements Serializable, Comparable<ExtendedRouteTag> {
+       private static final long serialVersionUID = 1L;
+       private final byte[] value;
+
+       public ExtendedRouteTag(final byte[] value) {
+               Preconditions.checkNotNull(value);
+               Preconditions.checkArgument(value.length == 8);
+               this.value = value;
+       }
+
+       @Override
+       public String toString(){
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("value", Arrays.toString(value));
+               return toStringHelper;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + Arrays.hashCode(value);
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               ExtendedRouteTag other = (ExtendedRouteTag) obj;
+               if (!Arrays.equals(value, other.value))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public int compareTo(final ExtendedRouteTag o) {
+               if (o == null)
+                       return 1;
+               if (o == this)
+                       return 0;
+               return SignedBytes.lexicographicalComparator().compare(value, o.value);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4InterfaceIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4InterfaceIdentifier.java
new file mode 100644 (file)
index 0000000..a00e9ff
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.base.Preconditions;
+
+public final class IPv4InterfaceIdentifier implements Comparable<IPv4InterfaceIdentifier>, InterfaceIdentifier {
+       private static final long serialVersionUID = 1L;
+       private final IPv4Address value;
+
+       /**
+        * Create a new unnumbered link identifier.
+        * 
+        * @param value Raw link identifier, has to be in range 1-4294967295
+        * @throws IllegalArgumentException when value is outside of allowed range
+        */
+       public IPv4InterfaceIdentifier(final IPv4Address value) {
+               Preconditions.checkNotNull(value, "Unsupported identifier value");
+               this.value = value;
+       }
+
+       /**
+        * Returns raw link identifier value.
+        * 
+        * @return value Raw link identifier value
+        */
+       public IPv4Address getValue() {
+               return this.value;
+       }
+
+       @Override
+       public int hashCode() {
+               return this.value.hashCode();
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final IPv4InterfaceIdentifier other = (IPv4InterfaceIdentifier) obj;
+               if (!this.value.equals(other.value))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public int compareTo(final IPv4InterfaceIdentifier other) {
+               if (this == other)
+                       return 0;
+               if (other == null)
+                       return 1;
+               return this.value.compareTo(other.value);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("IPv4InterfaceIdentifier [value=");
+               builder.append(this.value);
+               builder.append("]");
+               return builder.toString();
+       }
+
+       public static IPv4InterfaceIdentifier forString(final String string) {
+               Preconditions.checkNotNull(string);
+               return new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForString(string));
+       }
+
+       public static IPv4InterfaceIdentifier forBytes(final byte[] bytes) {
+               Preconditions.checkNotNull(bytes);
+               return new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForBytes(bytes));
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4PrefixIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4PrefixIdentifier.java
new file mode 100644 (file)
index 0000000..6e1a337
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+
+public final class IPv4PrefixIdentifier extends PrefixIdentifier<IPv4Address> {
+       private static final long serialVersionUID = 1L;
+
+       public IPv4PrefixIdentifier(final NodeIdentifier owner, final IPv4Prefix prefix) {
+               super(owner, prefix);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4Route.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4Route.java
new file mode 100644 (file)
index 0000000..9861c7d
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * Interface representing an IPv4 network route. This interface exists
+ * purely as a specialized extension on NetworkRoute to work around the
+ * loss of run-time information caused by type erasure.
+ */
+public interface IPv4Route extends NetworkRoute<IPv4Address> {
+
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4RouterIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv4RouterIdentifier.java
new file mode 100644 (file)
index 0000000..6c47583
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.base.Preconditions;
+
+public final class IPv4RouterIdentifier extends AbstractNetworkAddressRouterIdentifier<IPv4Address> {
+       private static final long serialVersionUID = 1L;
+
+       public IPv4RouterIdentifier(final IPv4Address address) {
+               super(address);
+       }
+
+       public static IPv4RouterIdentifier forString(final String string) {
+               Preconditions.checkNotNull(string);
+               return new IPv4RouterIdentifier(IPv4.FAMILY.addressForString(string));
+       }
+
+       public static IPv4RouterIdentifier forBytes(final byte[] bytes) {
+               Preconditions.checkNotNull(bytes);
+               return new IPv4RouterIdentifier(IPv4.FAMILY.addressForBytes(bytes));
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6InterfaceIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6InterfaceIdentifier.java
new file mode 100644 (file)
index 0000000..a7cc528
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import com.google.common.base.Preconditions;
+
+public final class IPv6InterfaceIdentifier implements Comparable<IPv6InterfaceIdentifier>, InterfaceIdentifier {
+       private static final long serialVersionUID = 1L;
+       private final IPv6Address value;
+
+       /**
+        * Create a new unnumbered link identifier.
+        * 
+        * @param value Raw link identifier, has to be in range 1-4294967295
+        * @throws IllegalArgumentException when value is outside of allowed range
+        */
+       public IPv6InterfaceIdentifier(final IPv6Address value) {
+               this.value = Preconditions.checkNotNull(value, "Unsupported identifier value");
+       }
+
+       /**
+        * Returns raw link identifier value.
+        * 
+        * @return value Raw link identifier value
+        */
+       public IPv6Address getValue() {
+               return this.value;
+       }
+
+       @Override
+       public int hashCode() {
+               return this.value.hashCode();
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final IPv6InterfaceIdentifier other = (IPv6InterfaceIdentifier) obj;
+               if (!this.value.equals(other.value))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public int compareTo(final IPv6InterfaceIdentifier other) {
+               if (this == other)
+                       return 0;
+               if (other == null)
+                       return 1;
+               return this.value.compareTo(other.value);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("IPv6InterfaceIdentifier [value=");
+               builder.append(this.value);
+               builder.append("]");
+               return builder.toString();
+       }
+
+       public static IPv6InterfaceIdentifier forString(final String string) {
+               Preconditions.checkNotNull(string);
+               return new IPv6InterfaceIdentifier(IPv6.FAMILY.addressForString(string));
+       }
+
+       public static IPv6InterfaceIdentifier forBytes(final byte[] bytes) {
+               Preconditions.checkNotNull(bytes);
+               return new IPv6InterfaceIdentifier(IPv6.FAMILY.addressForBytes(bytes));
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6PrefixIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6PrefixIdentifier.java
new file mode 100644 (file)
index 0000000..fc79e2f
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+
+public final class IPv6PrefixIdentifier extends PrefixIdentifier<IPv6Address> {
+       private static final long serialVersionUID = 1L;
+
+       public IPv6PrefixIdentifier(final NodeIdentifier owner, final IPv6Prefix prefix) {
+               super(owner, prefix);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6Route.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6Route.java
new file mode 100644 (file)
index 0000000..1ba0d92
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+
+/**
+ * Interface representing an IPv6 network route. This interface exists
+ * purely as a specialized extension on NetworkRoute to work around the
+ * loss of run-time information caused by type erasure.
+ */
+public interface IPv6Route extends NetworkRoute<IPv6Address> {
+
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6RouterIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/IPv6RouterIdentifier.java
new file mode 100644 (file)
index 0000000..1272c84
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import com.google.common.base.Preconditions;
+
+public final class IPv6RouterIdentifier extends AbstractNetworkAddressRouterIdentifier<IPv6Address> {
+       private static final long serialVersionUID = 1L;
+
+       public IPv6RouterIdentifier(final IPv6Address address) {
+               super(address);
+       }
+
+       public static IPv6RouterIdentifier forString(final String string) {
+               Preconditions.checkNotNull(string);
+               return new IPv6RouterIdentifier(IPv6.FAMILY.addressForString(string));
+       }
+
+       public static IPv6RouterIdentifier forBytes(final byte[] bytes) {
+               Preconditions.checkNotNull(bytes);
+               return new IPv6RouterIdentifier(IPv6.FAMILY.addressForBytes(bytes));
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISAreaIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISAreaIdentifier.java
new file mode 100644 (file)
index 0000000..2642295
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * @see https://tools.ietf.org/html/draft-ietf-idr-ls-distribution-03#section-3.3.1.2
+ */
+public final class ISISAreaIdentifier extends AbstractIdentifier<ISISAreaIdentifier> {
+       private static final long serialVersionUID = 1L;
+       private final byte[] id;
+
+       /**
+        * Construct a new Node Area identifier. This constructor expects
+        * a non-empty byte array which is the are distinguisher. Maximum
+        * length of the array is capped at 20 bytes.
+        *
+        * @param id Area identifier, expressed as a byte array
+        * @throws IllegalArgumentException if the identifier is not valid
+        */
+       public ISISAreaIdentifier(final byte[] id) {
+               this.id = Preconditions.checkNotNull(id);
+               Preconditions.checkArgument(id.length > 0 && id.length <= 20);
+       }
+
+       /**
+        * Access the underlying identifier.
+        * 
+        * @return Identifier bytearray of AreaIdentifier.
+        */
+       @Override
+       public final byte[] getBytes() {
+               return this.id;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("id", ByteArray.toHexString(id, "."));
+       }
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISLANIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISLANIdentifier.java
new file mode 100644 (file)
index 0000000..7156974
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * An IS-IS node identifier.
+ */
+public final class ISISLANIdentifier extends AbstractLANIdentifier<ISISRouterIdentifier> {
+       private static final long serialVersionUID = 1L;
+       private final short psn;
+
+       /**
+        * Construct a new node identifier. Formed as the unification of component identifiers.
+        *
+        * @param systemId ISO System ID, may not be null
+        */
+       public ISISLANIdentifier(final ISOSystemIdentifier systemId, final short psn) {
+               this(new ISISRouterIdentifier(systemId), psn);
+       }
+
+       public ISISLANIdentifier(final ISISRouterIdentifier dis, final short psn) {
+               super(dis);
+               Preconditions.checkArgument(psn > 0 && psn < 255);
+               this.psn = psn;
+       }
+
+       public short getPSN() {
+               return psn;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("psn", psn);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + psn;
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               ISISLANIdentifier other = (ISISLANIdentifier) obj;
+               if (psn != other.psn)
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISNetworkPrefix.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISNetworkPrefix.java
new file mode 100644 (file)
index 0000000..e78cf01
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * ISIS-specific prefix prefix advertisement.
+ * @param <T> Network Address type of the prefix being advertised
+ */
+public interface ISISNetworkPrefix<T extends NetworkAddress<?>> extends NetworkPrefix<T> {
+       @Override
+       public ISISNetworkPrefixState currentState();
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISNetworkPrefixState.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISNetworkPrefixState.java
new file mode 100644 (file)
index 0000000..1f07017
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.SortedSet;
+
+import org.opendaylight.protocol.bgp.linkstate.ExtendedRouteTag;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * ISIS-specific prefix prefix advertisement state.
+ */
+public class ISISNetworkPrefixState extends NetworkPrefixState {
+       private static final long serialVersionUID = 1L;
+       private final SortedSet<ExtendedRouteTag> extendedRouteTags;
+       private final boolean upDownBit;
+
+       public ISISNetworkPrefixState(NetworkPrefixState orig, SortedSet<ExtendedRouteTag> extendedRouteTags, boolean upDownBit) {
+               super(orig);
+               this.extendedRouteTags = extendedRouteTags;
+               this.upDownBit = upDownBit;
+       }
+
+       protected ISISNetworkPrefixState(ISISNetworkPrefixState orig) {
+               super(orig);
+               this.extendedRouteTags = orig.extendedRouteTags;
+               this.upDownBit = orig.upDownBit;
+       }
+
+       /**
+        * Returns the IS-IS extended route tags associated with this
+        * advertisement.
+        *
+        * @return IS-IS extended route tags, may be empty
+        */
+       public final SortedSet<ExtendedRouteTag> getExtendedRouteTags() {
+               return extendedRouteTags;
+       }
+
+       /**
+        * Returns the IS-IS Up/Down bit associated with this advertisement.
+        *
+        * @return Status of the IS-IS Up/Down bit
+        */
+       public final boolean getUpDownBit() {
+               return upDownBit;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("extendedRouteTags", this.extendedRouteTags);
+               toStringHelper.add("upDownBit", this.upDownBit);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISRouterIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/ISISRouterIdentifier.java
new file mode 100644 (file)
index 0000000..f15eb78
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * An IS-IS node identifier.
+ */
+public final class ISISRouterIdentifier implements RouterIdentifier {
+       private static final long serialVersionUID = 1L;
+       private final ISOSystemIdentifier systemId;
+
+       /**
+        * Construct a new node identifier. Formed as the unification of component identifiers.
+        * 
+        * @param systemId ISO System ID, may not be null
+        */
+       public ISISRouterIdentifier(final ISOSystemIdentifier systemId) {
+               this.systemId = Preconditions.checkNotNull(systemId, "ISO System Identifier is mandatory.");
+       }
+
+       public final ISOSystemIdentifier getSystemId() {
+               return this.systemId;
+       }
+
+       @Override
+       public final String toString() {
+               return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("systemId", this.systemId);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.systemId == null) ? 0 : this.systemId.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final ISISRouterIdentifier other = (ISISRouterIdentifier) obj;
+               if (this.systemId == null) {
+                       if (other.systemId != null)
+                               return false;
+               } else if (!this.systemId.equals(other.systemId))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/InterfaceIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/InterfaceIdentifier.java
new file mode 100644 (file)
index 0000000..9f06bdf
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+public interface InterfaceIdentifier extends Identifier {
+
+}
+
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LANIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LANIdentifier.java
new file mode 100644 (file)
index 0000000..a87376f
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+public interface LANIdentifier<T extends RouterIdentifier> extends RouterIdentifier {
+       public T getDesignatedRouter();
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LinkAnchor.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LinkAnchor.java
new file mode 100644 (file)
index 0000000..75cd533
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Identifier specifying a Link Anchor. A link is anchored by two nodes.
+ * In case there are multiple links between two nodes with the same
+ * directionality, each of them carries a different Interface Identifier.
+ */
+public final class LinkAnchor implements Identifier {
+
+       private static final long serialVersionUID = 4768211569568229262L;
+
+       private final NodeIdentifier nodeIdentifier;
+
+       private final InterfaceIdentifier interfaceIdentifier;
+
+       /**
+        * Construct a new link anchor.
+        *
+        * @param nodeIdentifier Node Identifier part, may not be null
+        * @param interfaceIdentifier Interface Identifier part, possibly null
+        */
+       public LinkAnchor(final NodeIdentifier nodeIdentifier, final InterfaceIdentifier interfaceIdentifier) {
+               if(nodeIdentifier == null)
+                       throw new NullPointerException("Can not create link anchor with null node identifier.");
+               this.nodeIdentifier = nodeIdentifier;
+               this.interfaceIdentifier = interfaceIdentifier;
+       }
+
+       /**
+        * Returns the Node Identifier part of this anchor.
+        *
+        * @return Node Identifier part
+        */
+       public NodeIdentifier getNodeIdentifier() {
+               return this.nodeIdentifier;
+       }
+
+       /**
+        * Returns the Interface Identifier part of this anchor.
+        *
+        * @return Interface Identifier part, may be null
+        */
+       public InterfaceIdentifier getInterfaceIdentifier() {
+               return this.interfaceIdentifier;
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("node", nodeIdentifier);
+               toStringHelper.add("interface", interfaceIdentifier);
+               return toStringHelper;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime
+                               * result
+                               + (this.interfaceIdentifier == null ? 0 : this.interfaceIdentifier
+                                               .hashCode());
+               result = prime * result
+                               + (this.nodeIdentifier == null ? 0 : this.nodeIdentifier.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final LinkAnchor other = (LinkAnchor) obj;
+               if (this.interfaceIdentifier == null) {
+                       if (other.interfaceIdentifier != null)
+                               return false;
+               } else if (!this.interfaceIdentifier.equals(other.interfaceIdentifier))
+                       return false;
+               if (this.nodeIdentifier == null) {
+                       if (other.nodeIdentifier != null)
+                               return false;
+               } else if (!this.nodeIdentifier.equals(other.nodeIdentifier))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LinkIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LinkIdentifier.java
new file mode 100644 (file)
index 0000000..0321a09
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * A network link identifier. An instance of this object uniquely identifies
+ * a link between two nodes.
+ */
+public final class LinkIdentifier implements Identifier {
+       private static final long serialVersionUID = 1L;
+       private final TopologyIdentifier topology;
+       private final LinkAnchor localAnchor, remoteAnchor;
+
+       /**
+        * Construct a new Link identifier based on its partial identifiers.
+        *
+        * @param topology Link topology identifier, may be null
+        * @param localAnchor Link local anchor
+        * @param remoteAnchor Link remote anchor
+        * @throws IllegalArgumentException when anchors do not have equal
+        *         source protocol
+        */
+       public LinkIdentifier(final TopologyIdentifier topology, final LinkAnchor localAnchor, final LinkAnchor remoteAnchor) {
+               this.topology = topology;
+               this.localAnchor = localAnchor;
+               this.remoteAnchor = remoteAnchor;
+       }
+
+       /**
+        * Returns the local anchor identifier.
+        *
+        * @return Local anchor identifier
+        */
+       public LinkAnchor getLocalAnchor() {
+               return localAnchor;
+       }
+
+       /**
+        * Returns the remote anchor identifier.
+        *
+        * @return Remove anchor identifier
+        */
+       public LinkAnchor getRemoteAnchor() {
+               return remoteAnchor;
+       }
+
+       /**
+        * Returns identifier of topology to which this link belongs.
+        *
+        * @return Link's topology identifier
+        */
+       public TopologyIdentifier getTopology() {
+               return topology;
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("topology", topology);
+               toStringHelper.add("localAnchor", localAnchor);
+               toStringHelper.add("remoteAnchor", remoteAnchor);
+               return toStringHelper;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (topology == null ? 0 : topology.hashCode());
+               result = prime * result + (localAnchor == null ? 0 : localAnchor.hashCode());
+               result = prime * result + (remoteAnchor == null ? 0 : remoteAnchor.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final LinkIdentifier other = (LinkIdentifier) obj;
+               if (localAnchor == null) {
+                       if (other.localAnchor != null)
+                               return false;
+               } else if (!localAnchor.equals(other.localAnchor))
+                       return false;
+               if (remoteAnchor == null) {
+                       if (other.remoteAnchor != null)
+                               return false;
+               } else if (!remoteAnchor.equals(other.remoteAnchor))
+                       return false;
+               if (topology == null) {
+                       if (other.topology != null)
+                               return false;
+               } else if (!topology.equals(other.topology))
+                       return false;
+               return true;
+       }
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LinkProtectionType.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LinkProtectionType.java
new file mode 100644 (file)
index 0000000..baca6c4
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+/**
+ * Enumeration of possibilities how a link can be protected.
+ * @see <a href="http://tools.ietf.org/html/rfc4202#section-2.2">RFC 4202</a>
+ */
+public enum LinkProtectionType {
+       /**
+        * If the link is of type Extra Traffic, it means that the link is
+        * protecting another link or links.  The LSPs on a link of this type
+        * will be lost if any of the links it is protecting fail.
+        */
+       EXTRA_TRAFFIC,
+       /**
+        * If the link is of type Unprotected, it means that there is no
+        * other link protecting this link.  The LSPs on a link of this type
+        * will be lost if the link fails.
+        */
+       UNPROTECTED,
+       /**
+        * If the link is of type Shared, it means that there are one or more
+        * disjoint links of type Extra Traffic that are protecting this
+        * link.  These Extra Traffic links are shared between one or more
+        * links of type Shared.
+        */
+       SHARED,
+       /**
+        * If the link is of type Dedicated 1:1, it means that there is one
+        * dedicated disjoint link of type Extra Traffic that is protecting
+        * this link.
+        */
+       DEDICATED_ONE_TO_ONE,
+       /**
+        * If the link is of type Dedicated 1+1, it means that a dedicated
+        * disjoint link is protecting this link.  However, the protecting
+        * link is not advertised in the link state database and is therefore
+        * not available for the routing of LSPs.
+        */
+       DEDICATED_ONE_PLUS_ONE,
+       /**
+        * If the link is of type Enhanced, it means that a protection scheme
+        * that is more reliable than Dedicated 1+1, e.g., 4 fiber
+        * BLSR/MS-SPRING, is being used to protect this link.
+        */
+       ENHANCED
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/MPLSProtocol.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/MPLSProtocol.java
new file mode 100644 (file)
index 0000000..97208c6
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+/**
+ * Enumeration of all supported signalling protocols which support tunnel
+ * establishment in a MPLS network.
+ */
+public enum MPLSProtocol {
+       /**
+        * Label Distribution Protocol. Specified by <a href="http://tools.ietf.org/html/rfc3036">RFC 3036</a>.
+        */
+       LDP,
+       /**
+        * Resource Reservation Protocol - Traffic Engineering. Specified by
+        * <a href="http://tools.ietf.org/html/rfc3209">RFC 3209</a>.
+        */
+       RSVPTE
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkAddressRouterIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkAddressRouterIdentifier.java
new file mode 100644 (file)
index 0000000..bcb677e
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+public interface NetworkAddressRouterIdentifier<T extends NetworkAddress<?>> extends RouterIdentifier {
+       public T getAddress();
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkLink.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkLink.java
new file mode 100644 (file)
index 0000000..9e9b984
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+
+/**
+ *
+ * A single link in network topology. Network link is a connecting line between
+ * two network nodes with bunch of attributes.
+ */
+public interface NetworkLink extends NetworkObject<LinkIdentifier> {
+       @Override
+       public NetworkLinkState currentState();
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkLinkImpl.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkLinkImpl.java
new file mode 100644 (file)
index 0000000..f1d9f0d
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.bgp.linkstate.AdministrativeGroup;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.MPLSProtocol;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLink;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+
+/**
+ * Implementation of {@link NetworkLink}
+ */
+public final class NetworkLinkImpl extends NetworkObjectImpl<LinkIdentifier> implements NetworkLink {
+       private static final long serialVersionUID = 5203163596015262211L;
+
+       /**
+        *
+        * @param name
+        *            {@link LinkIdentifier}
+        */
+       public NetworkLinkImpl(final LinkIdentifier name) {
+               this(name, NetworkLinkState.EMPTY);
+       }
+
+       /**
+        *
+        * @param name {@link LinkIdentifier}
+        * @param template {@link NetworkLink}
+        */
+       public NetworkLinkImpl(final LinkIdentifier name, final NetworkLinkState state) {
+               super(name, state);
+       }
+
+       @Override
+       public NetworkLinkState currentState() {
+               return (NetworkLinkState) super.currentState();
+       }
+
+       /**
+        *
+        * @param administrativeGroup
+        *            {@link AdministrativeGroup}
+        */
+       @Deprecated
+       public synchronized void setAdministrativeGroup(final AdministrativeGroup administrativeGroup) {
+               this.state = currentState().withAdministrativeGroup(administrativeGroup);
+       }
+
+       /**
+        *
+        * @param maximumBandwidth
+        *            {@link Bandwidth}
+        */
+       @Deprecated
+       public synchronized void setMaximumBandwidth(final Bandwidth maximumBandwidth) {
+               this.state = currentState().withMaximumBandwidth(maximumBandwidth);
+       }
+
+       /**
+        *
+        * @param reservableBandwidth
+        *            {@link Bandwidth}
+        */
+       @Deprecated
+       public synchronized void setMaximumReservableBandwidth(final Bandwidth reservableBandwidth) {
+               this.state = currentState().withReservableBandwidth(reservableBandwidth);
+       }
+
+       /**
+        *
+        * @param unreservedBandwidth
+        *            array of {@link Bandwidth}
+        */
+       @Deprecated
+       public synchronized void setUnreservedBandwidth(final Bandwidth[] unreservedBandwidth) {
+               this.state = currentState().withUnreservedBandwidth(unreservedBandwidth);
+       }
+
+       /**
+        *
+        * @param protectionType
+        *            {@link LinkProtectionType}
+        */
+       @Deprecated
+       public synchronized void setProtectionType(final LinkProtectionType protectionType) {
+               this.state = currentState().withProtectionType(protectionType);
+       }
+
+       /**
+        *
+        * @param enabledMPLSProtocols
+        *            set of {@link MPLSProtocol}
+        */
+       @Deprecated
+       public synchronized void setEnabledMPLSProtocols(final Set<MPLSProtocol> enabledMPLSProtocols) {
+               this.state = currentState().withEnabledMPLSProtocols(enabledMPLSProtocols);
+       }
+
+       /**
+        *
+        * @param sharedRiskLinkGroups
+        *            set of {@link SharedRiskLinkGroup}
+        */
+       @Deprecated
+       public synchronized void setSharedRiskLinkGroups(final Set<SharedRiskLinkGroup> sharedRiskLinkGroups) {
+               this.state = currentState().withSharedRiskLinkGroups(sharedRiskLinkGroups);
+       }
+
+       /**
+        *
+        * @param <T>
+        *            metric
+        * @param metric
+        *            T
+        */
+       @Deprecated
+       public synchronized <T extends Metric<?>> void setDefaultMetric(final T metric) {
+               this.state = currentState().withDefaultMetric(metric);
+       }
+
+       /**
+        *
+        * @param <T> metric
+        * @param metricType class
+        * @param metric T
+        */
+       @Deprecated
+       public synchronized <T extends Metric<T>> void setMetric(final Class<T> metricType, final T metric) {
+               this.state = currentState().withMetric(metricType, metric);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkLinkState.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkLinkState.java
new file mode 100644 (file)
index 0000000..82d490c
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.bgp.linkstate.AdministrativeGroup;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.MPLSProtocol;
+import org.opendaylight.protocol.util.DefaultingTypesafeContainer;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * 
+ * A single link in network topology. Network link is a connecting line between two network nodes with bunch of
+ * attributes.
+ */
+public final class NetworkLinkState extends NetworkObjectState {
+       public static final NetworkLinkState EMPTY = new NetworkLinkState();
+       private static final long serialVersionUID = 1L;
+       private final DefaultingTypesafeContainer<Metric<?>> metrics;
+       private Set<SharedRiskLinkGroup> sharedRiskLinkGroups;
+       private AdministrativeGroup administrativeGroup;
+       private Set<MPLSProtocol> enabledMPLSProtocols;
+       private LinkProtectionType protectionType;
+       private Bandwidth[] unreservedBandwidth;
+       private Bandwidth reservableBandwidth;
+       private Bandwidth maximumBandwidth;
+       private String symbolicName;
+
+       private NetworkLinkState() {
+               this(NetworkObjectState.EMPTY, new DefaultingTypesafeContainer<Metric<?>>(), null, LinkProtectionType.UNPROTECTED, null, null, null);
+       }
+
+       public NetworkLinkState(final NetworkObjectState orig, final DefaultingTypesafeContainer<Metric<?>> metrics,
+                       final Set<SharedRiskLinkGroup> sharedRiskLinkGroups, final AdministrativeGroup administrativeGroup,
+                       final Set<MPLSProtocol> enabledMPLSProtocols, final LinkProtectionType protectionType, final String symbolicName,
+                       final Bandwidth[] unreservedBandwidth, final Bandwidth reservableBandwidth,     final Bandwidth maximumBandwidth) {
+               super(orig);
+               this.metrics = Preconditions.checkNotNull(metrics, "Metric is mandatory.");
+               this.sharedRiskLinkGroups = sharedRiskLinkGroups;
+               this.administrativeGroup = administrativeGroup;
+               this.enabledMPLSProtocols = enabledMPLSProtocols;
+               this.protectionType = Preconditions.checkNotNull(protectionType);
+               this.symbolicName = symbolicName;
+               this.unreservedBandwidth = unreservedBandwidth;
+               this.reservableBandwidth = reservableBandwidth;
+               this.maximumBandwidth = maximumBandwidth;
+       }
+
+       public NetworkLinkState(final NetworkObjectState orig, final DefaultingTypesafeContainer<Metric<?>> metrics,
+                       final AdministrativeGroup administrativeGroup, final LinkProtectionType protectionType, final Bandwidth[] unreservedBandwidth,
+                       final Bandwidth reservableBandwidth, final Bandwidth maximumBandwidth) {
+               this(orig, metrics, Collections.<SharedRiskLinkGroup> emptySet(), administrativeGroup, Collections.<MPLSProtocol> emptySet(), protectionType,
+                               null, unreservedBandwidth, reservableBandwidth, maximumBandwidth);
+       }
+
+       protected NetworkLinkState(final NetworkLinkState orig) {
+               super(orig);
+               this.metrics = orig.metrics;
+               this.sharedRiskLinkGroups = orig.sharedRiskLinkGroups;
+               this.administrativeGroup = orig.administrativeGroup;
+               this.enabledMPLSProtocols = orig.enabledMPLSProtocols;
+               this.protectionType = orig.protectionType;
+               this.symbolicName = orig.symbolicName;
+               this.unreservedBandwidth = orig.unreservedBandwidth;
+               this.reservableBandwidth = orig.reservableBandwidth;
+               this.maximumBandwidth = orig.maximumBandwidth;
+       }
+
+       @Override
+       protected NetworkLinkState newInstance() {
+               return new NetworkLinkState(this);
+       }
+
+       /**
+        * Get AdministrativeGroup attribute of network link {@link AdministrativeGroup}.
+        * 
+        * @return AdministrativeGroup of network link.
+        */
+       public final AdministrativeGroup getAdministrativeGroup() {
+               return this.administrativeGroup;
+       }
+
+       public final NetworkLinkState withAdministrativeGroup(final AdministrativeGroup administrativeGroup) {
+               final NetworkLinkState ret = newInstance();
+               ret.administrativeGroup = administrativeGroup;
+               return ret;
+       }
+
+       /**
+        * Get maximum bandwidth attribute of network link {@link Bandwidth}.
+        * 
+        * @return Bandwidth maximum bandwidth of network link.
+        */
+       public final Bandwidth getMaximumBandwidth() {
+               return this.maximumBandwidth;
+       }
+
+       public final NetworkLinkState withMaximumBandwidth(final Bandwidth maximumBandwidth) {
+               final NetworkLinkState ret = newInstance();
+               ret.maximumBandwidth = maximumBandwidth;
+               return ret;
+       }
+
+       /**
+        * Get maximum reservable bandwidth attribute of network link {@link Bandwidth}.
+        * 
+        * @return Bandwidth maximum reservable bandwidth of network link.
+        */
+       public final Bandwidth getMaximumReservableBandwidth() {
+               return this.reservableBandwidth;
+       }
+
+       public final NetworkLinkState withReservableBandwidth(final Bandwidth reservableBandwidth) {
+               final NetworkLinkState ret = newInstance();
+               ret.reservableBandwidth = reservableBandwidth;
+               return ret;
+       }
+
+       /**
+        * Get unreserved bandwidth attribute of network link {@link Bandwidth}.
+        * 
+        * @return Bandwidth[] unreserved bandwidth of network link.
+        */
+       public final Bandwidth[] getUnreservedBandwidth() {
+               return this.unreservedBandwidth;
+       }
+
+       public final NetworkLinkState withUnreservedBandwidth(final Bandwidth[] unreservedBandwidth) {
+               Preconditions.checkNotNull(unreservedBandwidth);
+               Preconditions.checkArgument(unreservedBandwidth.length == 8);
+
+               final NetworkLinkState ret = newInstance();
+               ret.unreservedBandwidth = unreservedBandwidth;
+               return ret;
+       }
+
+       /**
+        * Get link protection type attribute of network link {@link LinkProtectionType}.
+        * 
+        * @return LinkProtectionType of network link.
+        */
+       public final LinkProtectionType getProtectionType() {
+               return this.protectionType;
+       }
+
+       public final NetworkObjectState withProtectionType(final LinkProtectionType protectionType) {
+               final NetworkLinkState ret = newInstance();
+               ret.protectionType = protectionType;
+               return ret;
+       }
+
+       /**
+        * Get set of enabled MPLSProtocols of network link {@link MPLSProtocol}.
+        * 
+        * @return Set<MPLSProtocol> enabled MPLSProtocols of network link.
+        */
+       public final Set<MPLSProtocol> getEnabledMPLSProtocols() {
+               return this.enabledMPLSProtocols;
+       }
+
+       public final NetworkLinkState withEnabledMPLSProtocols(final Set<MPLSProtocol> enabledMPLSProtocols) {
+               final NetworkLinkState ret = newInstance();
+               ret.enabledMPLSProtocols = enabledMPLSProtocols;
+               return ret;
+       }
+
+       /**
+        * Get set of SharedRiskLinkGroups of network link {@link SharedRiskLinkGroup}.
+        * 
+        * @return Set<SharedRiskLinkGroup> shared risk link groups of network link.
+        */
+       public final Set<SharedRiskLinkGroup> getSharedRiskLinkGroups() {
+               return this.sharedRiskLinkGroups;
+       }
+
+       public final NetworkLinkState withSharedRiskLinkGroups(final Set<SharedRiskLinkGroup> sharedRiskLinkGroups) {
+               Preconditions.checkNotNull(sharedRiskLinkGroups);
+               final NetworkLinkState ret = newInstance();
+               ret.sharedRiskLinkGroups = sharedRiskLinkGroups;
+               return ret;
+       }
+
+       /**
+        * Get default Metric attribute of network link {@link Metric}.
+        * 
+        * @return default Metric of network link.
+        */
+       public final Metric<?> getDefaultMetric() {
+               return this.metrics.getDefaultEntry();
+       }
+
+       public final <T extends Metric<?>> NetworkLinkState withDefaultMetric(final T metric) {
+               // FIXME: this violates API contract of State!
+               this.metrics.setDefaultEntry(metric);
+               return this;
+       }
+
+       /**
+        * Get metric attribute of submitted metric type of network link {@link Metric}.
+        * 
+        * @param <T> sub-type of metric.
+        * @param metricType which value should be returned.
+        * @return metric of submitted type of network link.
+        */
+       public final <T extends Metric<?>> T getMetric(final Class<? extends T> metricType) {
+               return this.metrics.getEntry(metricType);
+       }
+
+       public final <T extends Metric<T>> NetworkLinkState withMetric(final Class<T> metricType, final T metric) {
+               // FIXME: this violates API contract of State!
+               this.metrics.setEntry(metricType, metric);
+               return this;
+       }
+
+       public final String getSymbolicName() {
+               return this.symbolicName;
+       }
+
+       public final NetworkLinkState withSymbolicName(final String symbolicName) {
+               final NetworkLinkState ret = newInstance();
+               ret.symbolicName = symbolicName;
+               return ret;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("metrics", this.metrics);
+               toStringHelper.add("SRLGs", this.sharedRiskLinkGroups);
+               toStringHelper.add("administrativeGroup", this.administrativeGroup);
+               toStringHelper.add("enabledMPLSProtocols", this.enabledMPLSProtocols);
+               toStringHelper.add("protectionType", this.protectionType);
+               toStringHelper.add("unreservedBandwidth", this.unreservedBandwidth);
+               toStringHelper.add("reservableBandwidth", this.reservableBandwidth);
+               toStringHelper.add("maximumBandwidth", this.maximumBandwidth);
+               toStringHelper.add("symbolicName", this.symbolicName);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.administrativeGroup == null) ? 0 : this.administrativeGroup.hashCode());
+               result = prime * result + ((this.enabledMPLSProtocols == null) ? 0 : this.enabledMPLSProtocols.hashCode());
+               result = prime * result + ((this.maximumBandwidth == null) ? 0 : this.maximumBandwidth.hashCode());
+               result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+               result = prime * result + ((this.protectionType == null) ? 0 : this.protectionType.hashCode());
+               result = prime * result + ((this.symbolicName == null) ? 0 : this.symbolicName.hashCode());
+               result = prime * result + ((this.reservableBandwidth == null) ? 0 : this.reservableBandwidth.hashCode());
+               result = prime * result + ((this.sharedRiskLinkGroups == null) ? 0 : this.sharedRiskLinkGroups.hashCode());
+               result = prime * result + Arrays.hashCode(this.unreservedBandwidth);
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final NetworkLinkState other = (NetworkLinkState) obj;
+               if (this.administrativeGroup == null) {
+                       if (other.administrativeGroup != null)
+                               return false;
+               } else if (!this.administrativeGroup.equals(other.administrativeGroup))
+                       return false;
+               if (this.enabledMPLSProtocols == null) {
+                       if (other.enabledMPLSProtocols != null)
+                               return false;
+               } else if (!this.enabledMPLSProtocols.equals(other.enabledMPLSProtocols))
+                       return false;
+               if (this.maximumBandwidth == null) {
+                       if (other.maximumBandwidth != null)
+                               return false;
+               } else if (!this.maximumBandwidth.equals(other.maximumBandwidth))
+                       return false;
+               if (this.metrics == null) {
+                       if (other.metrics != null)
+                               return false;
+               } else if (!this.metrics.equals(other.metrics))
+                       return false;
+               if (this.symbolicName == null) {
+                       if (other.symbolicName != null)
+                               return false;
+               } else if (!this.symbolicName.equals(other.symbolicName))
+                       return false;
+               if (this.protectionType != other.protectionType)
+                       return false;
+               if (this.reservableBandwidth == null) {
+                       if (other.reservableBandwidth != null)
+                               return false;
+               } else if (!this.reservableBandwidth.equals(other.reservableBandwidth))
+                       return false;
+               if (this.sharedRiskLinkGroups == null) {
+                       if (other.sharedRiskLinkGroups != null)
+                               return false;
+               } else if (!this.sharedRiskLinkGroups.equals(other.sharedRiskLinkGroups))
+                       return false;
+               if (!Arrays.equals(this.unreservedBandwidth, other.unreservedBandwidth))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkNode.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkNode.java
new file mode 100644 (file)
index 0000000..af984a5
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+
+/**
+ * A single (router) node in the network topology. Nodes are interconnected by links and have a bunch of attributes. One
+ * of the key attributes is the set of prefixes for which this node acts as a network edge router.
+ */
+public interface NetworkNode extends NetworkObject<NodeIdentifier> {
+       @Override
+       public NetworkNodeState currentState();
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkNodeImpl.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkNodeImpl.java
new file mode 100644 (file)
index 0000000..e16c60a
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNode;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+
+/**
+ * Implementation of {@link NetworkNode}
+ */
+public class NetworkNodeImpl extends NetworkObjectImpl<NodeIdentifier> implements NetworkNode {
+       private static final long serialVersionUID = -7999816386632869087L;
+
+       /**
+        * 
+        * @param name {@link NodeIdentifier}
+        */
+       public NetworkNodeImpl(final NodeIdentifier name) {
+               this(name, NetworkNodeState.EMPTY);
+       }
+
+       /**
+        * 
+        * @param name {@link NodeIdentifier}
+        * @param template {@link NetworkNode}
+        */
+       public NetworkNodeImpl(final NodeIdentifier name, final NetworkNodeState state) {
+               super(name, state);
+       }
+
+       /**
+        * Standard setter for NetworkNode identifierAlterinatives attribute.
+        * 
+        * @param identifierAlternatives a set of all alternatives, has to include the primary identifier.
+        */
+       @Deprecated
+       public synchronized void setAlternativeIdentifiers(final Set<RouterIdentifier> identifierAlternatives) {
+               this.state = currentState().withIdentifierAlternatives(identifierAlternatives);
+       }
+
+       /**
+        * Standard setter for NetworkNode topologyMembership attribute.
+        * 
+        * @param topologyMembership map of {@link TopologyIdentifier} and {@link TopologyNodeInformation}
+        */
+       @Deprecated
+       public synchronized void setTopologyMembership(final Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership) {
+               this.state = currentState().withTopologyMembership(topologyMembership);
+       }
+
+       /**
+        * Standard setter for NetworkNode areaMembership attribute.
+        * 
+        * @param areaMembership set of {@link NodeAreaIdentifier}
+        */
+       @Deprecated
+       public synchronized void setAreaMembership(final Set<ISISAreaIdentifier> areaMembership) {
+               this.state = currentState().withAreaMembership(areaMembership);
+       }
+
+       /**
+        * Standard setter for NetworkNode isAreaBorderRouter attribute.
+        * 
+        * @param isAreaBorderRouter boolean
+        */
+       @Deprecated
+       public synchronized void setAreaBorderRouter(final boolean isAreaBorderRouter) {
+               this.state = currentState().withAreaBorderRouter(isAreaBorderRouter);
+       }
+
+       /**
+        * Standard setter for NetworkNode isExternal attribute.
+        * 
+        * @param isExternal boolean
+        */
+       @Deprecated
+       public synchronized void setExternal(final boolean isExternal) {
+               this.state = currentState().withExternal(isExternal);
+       }
+
+       /**
+        * 
+        * @param value hostName
+        */
+       @Deprecated
+       public synchronized void setDynamicHostname(final String value) {
+               this.state = currentState().withDynamicHostname(value);
+       }
+
+       @Override
+       public synchronized NetworkNodeState currentState() {
+               return (NetworkNodeState) super.currentState();
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkNodeState.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkNodeState.java
new file mode 100644 (file)
index 0000000..d362958
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * A single (router) node in the network topology. Nodes are interconnected by links and have a bunch of attributes. One
+ * of the key attributes is the set of prefixes for which this node acts as a network edge router.
+ */
+public class NetworkNodeState extends NetworkObjectState {
+       public static final NetworkNodeState EMPTY = new NetworkNodeState();
+       private static final long serialVersionUID = 1L;
+       private Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership;
+       private Set<ISISAreaIdentifier> areaMembership;
+       private boolean areaBorderRouter;
+       private boolean external;
+       private Set<RouterIdentifier> identifierAlternatives;
+       private String dynamicHostName;
+
+       private NetworkNodeState() {
+               this(NetworkObjectState.EMPTY, Collections.<TopologyIdentifier, TopologyNodeInformation> emptyMap(), Collections.<ISISAreaIdentifier> emptySet(), false, false, Collections.<RouterIdentifier> emptySet(), null);
+       }
+
+       public NetworkNodeState(final NetworkObjectState orig, final Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership,
+                       final Set<ISISAreaIdentifier> areaMembership, final boolean areaBorderRouter, final boolean external,
+                       final Set<RouterIdentifier> identifierAlternatives, final String dynamicHostName) {
+               super(orig);
+               Preconditions.checkNotNull(areaMembership);
+               Preconditions.checkNotNull(identifierAlternatives);
+               Preconditions.checkNotNull(topologyMembership);
+               this.topologyMembership = topologyMembership;
+               this.areaMembership = areaMembership;
+               this.areaBorderRouter = areaBorderRouter;
+               this.external = external;
+               this.identifierAlternatives = identifierAlternatives;
+               this.dynamicHostName = dynamicHostName;
+       }
+
+       protected NetworkNodeState(final NetworkNodeState orig) {
+               super(orig);
+               this.topologyMembership = orig.topologyMembership;
+               this.areaMembership = orig.areaMembership;
+               this.areaBorderRouter = orig.areaBorderRouter;
+               this.external = orig.external;
+               this.identifierAlternatives = orig.identifierAlternatives;
+               this.dynamicHostName = orig.dynamicHostName;
+       }
+
+       /**
+        * Get the per-topology information about this node.
+        * 
+        * @return An immutable map of per-topology state information
+        */
+       public final Map<TopologyIdentifier, TopologyNodeInformation> getTopologyMembership() {
+               return this.topologyMembership;
+       }
+
+       public final NetworkNodeState withTopologyMembership(final Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership) {
+               final NetworkNodeState ret = newInstance();
+               ret.topologyMembership = Collections.unmodifiableMap(topologyMembership);
+               return ret;
+       }
+
+       /**
+        * Get area membership information.
+        * 
+        * @return An immutable set containing identifiers of all node area this node is member of.
+        */
+       public final Set<ISISAreaIdentifier> getAreaMembership() {
+               return this.areaMembership;
+       }
+
+       public final NetworkNodeState withAreaMembership(final Set<ISISAreaIdentifier> areaMembership) {
+               final NetworkNodeState ret = newInstance();
+               ret.areaMembership = Collections.unmodifiableSet(areaMembership);
+               return ret;
+       }
+
+       /**
+        * Get ABR flag value. Area Border Routers (e.g. routers connected to multiple areas) advertise this flag.
+        * 
+        * @return True if this router is an ABR.
+        */
+       public final boolean isAreaBorderRouter() {
+               return this.areaBorderRouter;
+       }
+
+       public final NetworkNodeState withAreaBorderRouter(final boolean value) {
+               final NetworkNodeState ret = newInstance();
+               ret.areaBorderRouter = value;
+               return ret;
+       }
+
+       /**
+        * Get external flag value. This corresponds to <a href="http://tools.ietf.org/html/rfc2328">RFC 2328</a> definition
+        * of ExternalRoutingCapability. It is advertized by all routers connected to external ASes.
+        * 
+        * @return True if the router is an AS-border router
+        */
+       public final boolean isExternal() {
+               return this.external;
+       }
+
+       public final NetworkNodeState withExternal(final boolean value) {
+               final NetworkNodeState ret = newInstance();
+               ret.external = value;
+               return ret;
+       }
+
+       /**
+        * http://tools.ietf.org/html/rfc5301#section-3, encoded as a String. The string is guaranteed to contain US-ASCII
+        * characters.
+        * 
+        * @return dynamic hostname of the router that is connected
+        */
+       public final String getDynamicHostname() {
+               return this.dynamicHostName;
+       }
+
+       public final NetworkNodeState withDynamicHostname(final String value) {
+               Preconditions.checkNotNull(value);
+               Preconditions.checkArgument(value.length() >= 1);
+               Preconditions.checkArgument(value.length() <= 255);
+               Preconditions.checkArgument(CharMatcher.ASCII.matchesAllOf(value));
+
+               final NetworkNodeState ret = newInstance();
+               ret.dynamicHostName = value;
+               return ret;
+       }
+
+       /**
+        * Return the set of alternative identifiers to which this node responds. This set must contain the primary
+        * identifier.
+        * 
+        * @return set of identifier alternatives.
+        */
+       public final Set<RouterIdentifier> getIdentifierAlternatives() {
+               return this.identifierAlternatives;
+       }
+
+       public final NetworkNodeState withIdentifierAlternatives(final Set<RouterIdentifier> identifierAlternatives) {
+               final NetworkNodeState ret = newInstance();
+               ret.identifierAlternatives = identifierAlternatives;
+               return ret;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("topologyMembership", this.topologyMembership);
+               toStringHelper.add("areaMembership", this.areaMembership);
+               toStringHelper.add("external", this.external);
+               toStringHelper.add("ABR", this.areaBorderRouter);
+               toStringHelper.add("dynamicHostname", this.dynamicHostName);
+               toStringHelper.add("routerIdentifiers", this.identifierAlternatives);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+       @Override
+       protected NetworkNodeState newInstance() {
+               return new NetworkNodeState(this);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkObject.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkObject.java
new file mode 100644 (file)
index 0000000..03b2e42
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.io.Serializable;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.concepts.NamedObject;
+import org.opendaylight.protocol.concepts.Stateful;
+
+/**
+ * Class representing an generic object living in a network. Each such object
+ * has a name which uniquely identifies it in a particular network. Further
+ * generic attributes provide view into how a particular object has been tagged
+ * in BGP world.
+ * 
+ * @param <T>
+ */
+public interface NetworkObject<T extends Identifier> extends NamedObject<T>, Serializable, Stateful<NetworkObjectState> {
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkObjectImpl.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkObjectImpl.java
new file mode 100644 (file)
index 0000000..d9a23c8
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObject;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Implementation of {@link NetworkObject}
+ *
+ * @param <T> {@link Identifier} type
+ */
+public class NetworkObjectImpl<T extends Identifier> implements NetworkObject<T> {
+       private static final long serialVersionUID = 1L;
+       private final T name;
+       protected NetworkObjectState state;
+
+       /**
+        *
+        * @param name
+        */
+       public NetworkObjectImpl(final T name) {
+               this(name, NetworkObjectState.EMPTY);
+       }
+
+       /**
+        *
+        * @param name T
+        * @param template T
+        */
+       public NetworkObjectImpl(final T name, final NetworkObjectState state) {
+               Preconditions.checkNotNull(name);
+               Preconditions.checkNotNull(state);
+               this.name = name;
+               this.state = state;
+       }
+
+       @Override
+       public final T getName() {
+               return this.name;
+       }
+
+       /**
+        * Standard setter for NetworkObject asPath attribute.
+        *
+        * @param asPath
+        *            {@link ASPath}
+        */
+       public final synchronized void setASPath(final ASPath asPath) {
+               this.state = state.withASPath(asPath);
+       }
+
+       /**
+        * Standard setter for NetworkObject communities attribute.
+        *
+        * @param communities
+        *            {@link Community}
+        */
+       public final synchronized void setCommunities(final Set<Community> communities) {
+               this.state = state.withCommunities(Collections.unmodifiableSet(communities));
+       }
+
+       /**
+        * Standard setter for NetworkObject extendedCommunities attribute.
+        *
+        * @param extendedCommunities
+        *            {@link ExtendedCommunity}
+        */
+       public final synchronized void setExtendedCommunities(
+                       final Set<ExtendedCommunity> extendedCommunities) {
+               this.state = state.withExtendedCommunities(Collections.unmodifiableSet(extendedCommunities));
+       }
+
+       @Override
+       public synchronized final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("name", name);
+               toStringHelper.add("state", state);
+               return toStringHelper;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof NetworkObjectImpl))
+                       return false;
+               final NetworkObjectImpl<?> other = (NetworkObjectImpl<?>) obj;
+               if (this.name == null) {
+                       if (other.name != null)
+                               return false;
+               } else if (!this.name.equals(other.name))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public synchronized NetworkObjectState currentState() {
+               return state;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkObjectState.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkObjectState.java
new file mode 100644 (file)
index 0000000..efad3c1
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+
+import org.opendaylight.protocol.concepts.State;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Class representing state of a generic object living somewhere in the network. Each such object has potentially
+ * arrived through BGP-like inter-domain distribution channel and thus contains equivalent tags -- which may be empty.
+ */
+public class NetworkObjectState implements State {
+       public static final NetworkObjectState EMPTY = new NetworkObjectState();
+       private static final long serialVersionUID = 1L;
+       private Set<ExtendedCommunity> extendedCommunities;
+       private Set<Community> communities;
+       private ASPath asPath;
+
+       protected NetworkObjectState() {
+               this(ASPath.EMPTY, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+       }
+
+       public NetworkObjectState(final ASPath asPath, final Set<Community> communities, final Set<ExtendedCommunity> extendedCommunities) {
+               this.asPath = asPath;
+               this.communities = communities;
+               this.extendedCommunities = extendedCommunities;
+       }
+
+       protected NetworkObjectState(final NetworkObjectState orig) {
+               this.asPath = orig.asPath;
+               this.communities = orig.communities;
+               this.extendedCommunities = orig.extendedCommunities;
+       }
+
+       /**
+        * Get the AS path from the local network to the object. This may be null if the installing source has no idea about
+        * ASes, as would be the case of network nodes learned from an IGP.
+        * 
+        * @return Path to the advertising Autonomous System.
+        */
+       public final ASPath getASPath() {
+               return this.asPath;
+       }
+
+       public final NetworkObjectState withASPath(final ASPath asPath) {
+               final NetworkObjectState ret = newInstance();
+               ret.asPath = asPath;
+               return ret;
+       }
+
+       /**
+        * Get BGP communities associated with this object. If this object has no RFC1997 extended communities attached, the
+        * returned set will be empty.
+        * 
+        * @return A set of RFC1997 communities.
+        */
+       public final Set<Community> getCommunities() {
+               return this.communities;
+       }
+
+       public final NetworkObjectState withCommunities(final Set<Community> communities) {
+               final NetworkObjectState ret = newInstance();
+               ret.communities = communities;
+               return ret;
+       }
+
+       /**
+        * Get BGP communities associated with this object. If this object has no RFC4360 extended communities attached, the
+        * returned set will be empty.
+        * 
+        * @return A set of RFC4360 extended communities.
+        */
+       public final Set<ExtendedCommunity> getExtendedCommunities() {
+               return this.extendedCommunities;
+       }
+
+       public final NetworkObjectState withExtendedCommunities(final Set<ExtendedCommunity> extendedCommunities) {
+               final NetworkObjectState ret = newInstance();
+               ret.extendedCommunities = extendedCommunities;
+               return ret;
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("ASPath", this.asPath);
+               toStringHelper.add("communities", this.communities);
+               toStringHelper.add("extendedCommunities", this.extendedCommunities);
+               return toStringHelper;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.asPath == null) ? 0 : this.asPath.hashCode());
+               result = prime * result + ((this.communities == null) ? 0 : this.communities.hashCode());
+               result = prime * result + ((this.extendedCommunities == null) ? 0 : this.extendedCommunities.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final NetworkObjectState other = (NetworkObjectState) obj;
+               if (this.asPath == null) {
+                       if (other.asPath != null)
+                               return false;
+               } else if (!this.asPath.equals(other.asPath))
+                       return false;
+               if (this.communities == null) {
+                       if (other.communities != null)
+                               return false;
+               } else if (!this.communities.equals(other.communities))
+                       return false;
+               if (this.extendedCommunities == null) {
+                       if (other.extendedCommunities != null)
+                               return false;
+               } else if (!this.extendedCommunities.equals(other.extendedCommunities))
+                       return false;
+               return true;
+       }
+
+       protected NetworkObjectState newInstance() {
+               return new NetworkObjectState(this);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkPrefix.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkPrefix.java
new file mode 100644 (file)
index 0000000..448d6e3
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+
+/**
+ * Generic, IGP-independent prefix advertisement.
+ * @param <T> Network Address type of the prefix
+ */
+public interface NetworkPrefix<T extends NetworkAddress<?>> extends NetworkObject<PrefixIdentifier<T>> {
+       @Override
+       public NetworkPrefixState currentState();
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkPrefixState.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkPrefixState.java
new file mode 100644 (file)
index 0000000..ca793f3
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.bgp.linkstate.RouteTag;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Generic, IGP-independent prefix advertisement.
+ * @param <T> Network Address type of the prefix
+ */
+public class NetworkPrefixState extends NetworkObjectState {
+       public static final NetworkPrefixState EMPTY = new NetworkPrefixState();
+       private static final long serialVersionUID = 1L;
+       private SortedSet<RouteTag> routeTags;
+       private Metric<?> metric;
+
+       private NetworkPrefixState() {
+               this(NetworkObjectState.EMPTY, new TreeSet<RouteTag>(), null);
+       }
+
+       protected NetworkPrefixState(NetworkPrefixState orig) {
+               super(orig);
+               this.metric = orig.metric;
+               this.routeTags = orig.routeTags;
+       }
+
+       public NetworkPrefixState(NetworkObjectState orig, SortedSet<RouteTag> routeTags, Metric<?> metric) {
+               super(orig);
+               Preconditions.checkNotNull(routeTags);
+               this.metric = metric;
+               this.routeTags = routeTags;
+       }
+
+       /**
+        * Return the prefix metric attached to this advertisement.
+        *
+        * @return Prefix metric, possibly null
+        */
+       public final Metric<?> getPrefixMetric() {
+               return metric;
+       }
+
+       public final NetworkPrefixState withPrefixMetric(Metric<?> metric) {
+               final NetworkPrefixState ret = newInstance();
+               ret.metric = metric;
+               return ret;
+       }
+
+       /**
+        * Return the route tag attached to this advertisement.
+        *
+        * @return Route tag, possibly null
+        */
+       public final SortedSet<RouteTag> getRouteTags() {
+               return routeTags;
+       }
+
+       public final NetworkPrefixState withRouteTags(SortedSet<RouteTag> routeTags) {
+               final NetworkPrefixState ret = newInstance();
+               ret.routeTags = routeTags;
+               return ret;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("metric", metric);
+               toStringHelper.add("routeTags", routeTags);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+       @Override
+       protected NetworkPrefixState newInstance() {
+               return new NetworkPrefixState(this);
+       }
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkRoute.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkRoute.java
new file mode 100644 (file)
index 0000000..f3980cd
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ * A single route existing within the network. A route is a way how to get from
+ * the local node to a set of network addresses. The set of addresses is
+ * represented as a Prefix of a particular address type and is the unique
+ * identifier for the route. The routing part is represented as the
+ * directly-connected neighbor, which should be used used as a relay for traffic
+ * going to the set of addresses.
+ *
+ * @param <T>
+ */
+public interface NetworkRoute<T extends NetworkAddress<?>> extends NetworkObject<Prefix<T>> {
+       @Override
+       public NetworkRouteState<T> currentState();
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkRouteState.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NetworkRouteState.java
new file mode 100644 (file)
index 0000000..d10b938
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.bgp.concepts.NextHop;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Preconditions;
+
+/**
+ * A single route existing within the network. A route is a way how to get from the local node to a set of network
+ * addresses. The set of addresses is represented as a Prefix of a particular address type and is the unique identifier
+ * for the route. The routing part is represented as the directly-connected neighbor, which should be used used as a
+ * relay for traffic going to the set of addresses.
+ * 
+ * @param <T>
+ */
+public final class NetworkRouteState<T extends NetworkAddress<?>> extends NetworkObjectState {
+       private static final long serialVersionUID = 1L;
+       private final NextHop<T> nextHop;
+
+       public NetworkRouteState(final NextHop<T> nextHop) {
+               this(NetworkObjectState.EMPTY, nextHop);
+       }
+
+       public NetworkRouteState(final NetworkObjectState orig, final NextHop<T> nextHop) {
+               super(orig);
+               this.nextHop = Preconditions.checkNotNull(nextHop);
+       }
+
+       protected NetworkRouteState(final NetworkRouteState<T> orig) {
+               super(orig);
+               this.nextHop = orig.nextHop;
+       }
+
+       @Override
+       protected NetworkRouteState<T> newInstance() {
+               return new NetworkRouteState<T>(this);
+       }
+
+       /**
+        * Get the relay for the set of addresses covered by this route.
+        * 
+        * @return NextHop<T> next hop.
+        */
+       public NextHop<T> getNextHop() {
+               return this.nextHop;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.nextHop == null) ? 0 : this.nextHop.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final NetworkRouteState<?> other = (NetworkRouteState<?>) obj;
+               if (this.nextHop == null) {
+                       if (other.nextHop != null)
+                               return false;
+               } else if (!this.nextHop.equals(other.nextHop))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NodeIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NodeIdentifier.java
new file mode 100644 (file)
index 0000000..162b813
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * A network node identifier. A network node is typically a router, a switch, or similar entity.
+ */
+public final class NodeIdentifier implements Identifier {
+       private static final long serialVersionUID = 1L;
+
+       private final ASNumber asNumber;
+       private final DomainIdentifier domainIdentifier;
+       private final AreaIdentifier areaIdentifier;
+       private final RouterIdentifier routerIdentifier;
+
+       public NodeIdentifier(final ASNumber as, final DomainIdentifier domain, final AreaIdentifier area, final RouterIdentifier router) {
+               this.routerIdentifier = Preconditions.checkNotNull(router, "Router Identifier is mandatory.");
+               this.asNumber = as;
+               this.domainIdentifier = domain;
+               this.areaIdentifier = area;
+       }
+
+       /**
+        * Return the AS number where this node resides.
+        * 
+        * @return AS of residence
+        */
+       public ASNumber getAsNumber() {
+               return this.asNumber;
+       }
+
+       public DomainIdentifier getDomainIdentifier() {
+               return this.domainIdentifier;
+       }
+
+       public AreaIdentifier getAreaIdentifier() {
+               return this.areaIdentifier;
+       }
+
+       public RouterIdentifier getRouterIdentifier() {
+               return this.routerIdentifier;
+       }
+
+       @Override
+       public String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("as", this.asNumber);
+               toStringHelper.add("domain", this.domainIdentifier);
+               toStringHelper.add("area", this.areaIdentifier);
+               toStringHelper.add("router", this.routerIdentifier);
+               return toStringHelper;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.areaIdentifier == null) ? 0 : this.areaIdentifier.hashCode());
+               result = prime * result + ((this.asNumber == null) ? 0 : this.asNumber.hashCode());
+               result = prime * result + ((this.domainIdentifier == null) ? 0 : this.domainIdentifier.hashCode());
+               result = prime * result + ((this.routerIdentifier == null) ? 0 : this.routerIdentifier.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final NodeIdentifier other = (NodeIdentifier) obj;
+               if (this.areaIdentifier == null) {
+                       if (other.areaIdentifier != null)
+                               return false;
+               } else if (!this.areaIdentifier.equals(other.areaIdentifier))
+                       return false;
+               if (this.asNumber == null) {
+                       if (other.asNumber != null)
+                               return false;
+               } else if (!this.asNumber.equals(other.asNumber))
+                       return false;
+               if (this.domainIdentifier == null) {
+                       if (other.domainIdentifier != null)
+                               return false;
+               } else if (!this.domainIdentifier.equals(other.domainIdentifier))
+                       return false;
+               if (this.routerIdentifier == null) {
+                       if (other.routerIdentifier != null)
+                               return false;
+               } else if (!this.routerIdentifier.equals(other.routerIdentifier))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NodeIdentifierFactory.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/NodeIdentifierFactory.java
new file mode 100644 (file)
index 0000000..3aec599
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public final class NodeIdentifierFactory {
+       private final ASNumber as;
+       private final DomainIdentifier domain;
+       private final AreaIdentifier area;
+
+       public NodeIdentifierFactory(final ASNumber as, final DomainIdentifier domain, final AreaIdentifier area) {
+               this.as = as;
+               this.area = area;
+               this.domain = domain;
+       }
+
+       public NodeIdentifier identifierForRouter(final RouterIdentifier router) {
+               return new NodeIdentifier(as, domain, area, router);
+       }
+
+       public static NodeIdentifier localIdentifier(final RouterIdentifier router) {
+               return new NodeIdentifier(null, null, null, router);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFInterfaceIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFInterfaceIdentifier.java
new file mode 100644 (file)
index 0000000..cab6d0b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * An OSPFv3 interface identifier.
+ * 
+ * @see https://tools.ietf.org/html/draft-ietf-idr-ls-distribution-03#section-3.2.1.4
+ */
+public final class OSPFInterfaceIdentifier implements InterfaceIdentifier {
+       private static final long serialVersionUID = 1L;
+       private final byte[] value;
+
+       public OSPFInterfaceIdentifier(final byte[] value) {
+               Preconditions.checkNotNull(value);
+               Preconditions.checkArgument(value.length == 4);
+               this.value = value;
+       }
+
+       public byte[] getValue() {
+               return this.value;
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("value", Arrays.toString(this.value));
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + Arrays.hashCode(this.value);
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final OSPFInterfaceIdentifier other = (OSPFInterfaceIdentifier) obj;
+               if (!Arrays.equals(this.value, other.value))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFNetworkPrefix.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFNetworkPrefix.java
new file mode 100644 (file)
index 0000000..7148b08
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * OSPF-specific prefix prefix advertisement.
+ * @param <T> Network Address type of the prefix being advertised
+ */
+public interface OSPFNetworkPrefix<T extends NetworkAddress<?>> extends NetworkPrefix<T> {
+       @Override
+       public OSPFNetworkPrefixState<T> currentState();
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFNetworkPrefixState.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFNetworkPrefixState.java
new file mode 100644 (file)
index 0000000..8941d47
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * OSPF-specific prefix prefix advertisement.
+ * @param <T> Network Address type of the prefix being advertised
+ */
+public class OSPFNetworkPrefixState<T extends NetworkAddress<?>> extends NetworkPrefixState {
+       private static final long serialVersionUID = 1L;
+       private final T forwardingAddress;
+
+       protected OSPFNetworkPrefixState(OSPFNetworkPrefixState<T> orig) {
+               super(orig);
+               this.forwardingAddress = orig.forwardingAddress;
+       }
+
+       public OSPFNetworkPrefixState(NetworkPrefixState orig, T forwardingAddress) {
+               super(orig);
+               this.forwardingAddress = forwardingAddress;
+       }
+
+       /**
+        * Returns the OSPF forwarding address attached to this advertisement.
+        *
+        * @return OSPF forwarding address
+        */
+       public final T getForwardingAddress() {
+               return forwardingAddress;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("forwardingAddress", this.forwardingAddress);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFPrefixIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFPrefixIdentifier.java
new file mode 100644 (file)
index 0000000..bdb86b0
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.concepts.Prefix;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * A network node identifier. A network node is typically a router, a switch, or similar entity.
+ */
+public final class OSPFPrefixIdentifier<T extends NetworkAddress<?>> extends PrefixIdentifier<T> {
+       private static final long serialVersionUID = 1L;
+       private final OSPFRouteType routeType;
+
+       public OSPFPrefixIdentifier(final NodeIdentifier owner, final Prefix<T> prefix, final OSPFRouteType routeType) {
+               super(owner, prefix);
+               this.routeType = routeType;
+       }
+
+       /**
+        * Returns OSPF Route Type.
+        * 
+        * @return {@link OSPFRouteType}
+        */
+       public OSPFRouteType getRouteType() {
+               return routeType;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("routeType", routeType);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((routeType == null) ? 0 : routeType.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               OSPFPrefixIdentifier<?> other = (OSPFPrefixIdentifier<?>) obj;
+               if (routeType != other.routeType)
+                       return false;
+               return true;
+       }
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFRouteType.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFRouteType.java
new file mode 100644 (file)
index 0000000..699cb86
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+/**
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-idr-ls-distribution-02#section-3.2.1.4">OSPF Route Type SubTLV</a>
+ */
+public enum OSPFRouteType {
+       Intra_Area, Inter_Area, External1, External2, NSSA1, NSSA2
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFRouterIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFRouterIdentifier.java
new file mode 100644 (file)
index 0000000..f298366
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * An OSPF node identifier.
+ */
+public final class OSPFRouterIdentifier implements RouterIdentifier {
+       private static final long serialVersionUID = 1L;
+       private final byte[] routerId;
+
+       /**
+        * Construct a new node identifier. Formed as the unification of component identifiers.
+        * 
+        * @param routerId OSPF Router ID
+        */
+       public OSPFRouterIdentifier(final byte[] routerId) {
+               Preconditions.checkNotNull(routerId, "Router identifier may not be null");
+               // @see https://tools.ietf.org/html/draft-ietf-idr-ls-distribution-03#section-3.2.1.4
+               Preconditions.checkArgument(routerId.length == 4, "Router identifier must be 4 bytes long");
+               this.routerId = routerId;
+       }
+
+       public byte[] getRouterId() {
+               return this.routerId;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + Arrays.hashCode(this.routerId);
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final OSPFRouterIdentifier other = (OSPFRouterIdentifier) obj;
+               if (!Arrays.equals(this.routerId, other.routerId))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public final String toString() {
+               return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("routerID", Arrays.toString(this.routerId));
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFv2LANIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFv2LANIdentifier.java
new file mode 100644 (file)
index 0000000..62a40aa
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+
+/**
+ * An OSPFv2 LAN "pseudonode" identifier
+ * @see https://tools.ietf.org/html/draft-ietf-idr-ls-distribution-03#section-3.2.1.4
+ */
+public final class OSPFv2LANIdentifier extends AbstractOSPFLANIdentifier<IPv4InterfaceIdentifier> {
+       private static final long serialVersionUID = 1L;
+
+       public OSPFv2LANIdentifier(final OSPFRouterIdentifier dr, final IPv4InterfaceIdentifier lanInterface) {
+               super(dr, lanInterface);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFv3LANIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/OSPFv3LANIdentifier.java
new file mode 100644 (file)
index 0000000..c58d9a5
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+
+/**
+ * An OSPFv3 LAN "pseudonode" identifier
+ * @see https://tools.ietf.org/html/draft-ietf-idr-ls-distribution-03#section-3.2.1.4
+ */
+public final class OSPFv3LANIdentifier extends AbstractOSPFLANIdentifier<OSPFInterfaceIdentifier> {
+       private static final long serialVersionUID = 1L;
+
+       public OSPFv3LANIdentifier(final OSPFRouterIdentifier dr, final OSPFInterfaceIdentifier lanInterface) {
+               super(dr, lanInterface);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/PrefixIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/PrefixIdentifier.java
new file mode 100644 (file)
index 0000000..eb5037f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.concepts.Prefix;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * A network node identifier. A network node is typically a router, a switch, or similar entity.
+ */
+public class PrefixIdentifier<T extends NetworkAddress<?>> implements Identifier {
+       private static final long serialVersionUID = 1L;
+       private final NodeIdentifier owner;
+       private final Prefix<T> prefix;
+
+       public PrefixIdentifier(final NodeIdentifier owner, final Prefix<T> prefix) {
+               this.owner = Preconditions.checkNotNull(owner);
+               this.prefix = Preconditions.checkNotNull(prefix);
+       }
+
+       public final NodeIdentifier getOwner() {
+               return owner;
+       }
+
+       /**
+        * Return the Prefix.
+        * 
+        * @return prefix
+        */
+       public final Prefix<T> getPrefix() {
+               return prefix;
+       }
+
+       @Override
+       public final String toString(){
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("owner", owner);
+               toStringHelper.add("prefix", prefix);
+               return toStringHelper;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((owner == null) ? 0 : owner.hashCode());
+               result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               PrefixIdentifier<?> other = (PrefixIdentifier<?>) obj;
+               if (owner == null) {
+                       if (other.owner != null)
+                               return false;
+               } else if (!owner.equals(other.owner))
+                       return false;
+               if (prefix == null) {
+                       if (other.prefix != null)
+                               return false;
+               } else if (!prefix.equals(other.prefix))
+                       return false;
+               return true;
+       }
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/RouteTag.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/RouteTag.java
new file mode 100644 (file)
index 0000000..63dda1d
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.SignedBytes;
+
+public final class RouteTag implements Serializable, Comparable<RouteTag> {
+       private static final long serialVersionUID = 1L;
+       private final byte[] value;
+
+       public RouteTag(final byte[] value) {
+               Preconditions.checkNotNull(value);
+               Preconditions.checkArgument(value.length == 4);
+               this.value = value;
+       }
+
+       @Override
+       public String toString(){
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("value", value);
+               return toStringHelper;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + Arrays.hashCode(value);
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               RouteTag other = (RouteTag) obj;
+               if (!Arrays.equals(value, other.value))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public int compareTo(RouteTag o) {
+               if (o == null)
+                       return 1;
+               if (o == this)
+                       return 0;
+               return SignedBytes.lexicographicalComparator().compare(value, o.value);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/RouterIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/RouterIdentifier.java
new file mode 100644 (file)
index 0000000..9fc38bc
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+public interface RouterIdentifier extends Identifier {
+
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/SourceProtocol.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/SourceProtocol.java
new file mode 100644 (file)
index 0000000..d3f6363
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+/**
+ * Enumeration of all protocols which may source link-state information.
+ */
+public enum SourceProtocol {
+       /**
+        * IS-IS Level 1 adjacency
+        */
+       ISISLevel1,
+       /**
+        * IS-IS Level 2 adjacency
+        */
+       ISISLevel2,
+       /**
+        * OSPF adjacency
+        */
+       OSPF,
+       /**
+        * Local run-time state. Learned by the advertising entity by
+        * seeing its directly-attached neighbors.
+        */
+       Direct,
+       /**
+        * Local configuration. Defined statically by an operator at the
+        * advertising entity.
+        */
+       Static,
+       /**
+        * Unknown source. Use this value if the others do not fit how we
+        * came by the information.
+        */
+       Unknown
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/TopologyIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/TopologyIdentifier.java
new file mode 100644 (file)
index 0000000..8880b5d
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.nio.ByteBuffer;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Topology identifier. This identifier is used in multi-topology networks,
+ * e.g. when there are multiple logical network built on top of a set of
+ * physical components. Usually routing happens only within a single topology,
+ * but nodes resident in multiple topologies can act as inter-topology
+ * gateways.
+ */
+public final class TopologyIdentifier extends AbstractIdentifier<TopologyIdentifier> {
+       private static final long serialVersionUID = 8386493752725436667L;
+       private final short id;
+
+       /**
+        * Construct a new topology identifier for a numeric ID.
+        *
+        * @param id Topology identifier. Valid range is 0-4095.
+        */
+       public TopologyIdentifier(final long id) {
+               if (id < 0 || id > 4095)
+                       throw new IllegalArgumentException("Invalid topology identifier");
+               this.id = (short) id;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + this.id;
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final TopologyIdentifier other = (TopologyIdentifier) obj;
+               if (this.id != other.id)
+                       return false;
+               return true;
+       }
+
+       @Override
+       protected byte[] getBytes() {
+               final ByteBuffer bb = ByteBuffer.allocate(Short.SIZE);
+               bb.putShort(this.id);
+               return bb.array();
+       }
+
+       /**
+        * Return ID attribute of Topology Identifier.
+        *
+        * @return Topology identifier
+        */
+       public short getId() {
+               return this.id;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("id", id);
+       }
+}
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/TopologyNodeInformation.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/TopologyNodeInformation.java
new file mode 100644 (file)
index 0000000..bd9c298
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import java.io.Serializable;
+
+/**
+ * Class representing per-Topology information about a Node. A node
+ * in this context is typically a router, which has a few properties
+ * which may be virtualized so as to have different values in topologies
+ * in which the node participates.
+ */
+public final class TopologyNodeInformation implements Serializable {
+       private static final long serialVersionUID = -3310738851831793539L;
+       private final boolean attached, overloaded;
+
+       /**
+        * Create a new per-topology object.
+        *
+        * @param isAttached Flag indicating the node is attached
+        * @param isOverloaded Flag indicating the node is overloaded
+        */
+       public TopologyNodeInformation(final boolean isAttached, final boolean isOverloaded) {
+               this.attached = isAttached;
+               this.overloaded = isOverloaded;
+       }
+
+       /**
+        * Check if node is attached.
+        *
+        * @return True if the node is attached
+        */
+       public boolean isAttached() {
+               return this.attached;
+       }
+
+       /**
+        * Check if the node is overloaded. An overloaded noded should
+        * not be assigned new traffic.
+        *
+        * @return True if the node experiences overload
+        */
+       public boolean isOverloaded() {
+               return this.overloaded;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (this.attached ? 1231 : 1237);
+               result = prime * result + (this.overloaded ? 1231 : 1237);
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof TopologyNodeInformation))
+                       return false;
+               final TopologyNodeInformation other = (TopologyNodeInformation) obj;
+               if (this.attached != other.attached)
+                       return false;
+               if (this.overloaded != other.overloaded)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder sb = new StringBuilder();
+               sb.append("TopologyNodeInformation [attached=");
+               sb.append(this.attached);
+               sb.append(", overloaded=");
+               sb.append(this.overloaded);
+               sb.append("]");
+               return sb.toString();
+       }
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/UniverseIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/UniverseIdentifier.java
new file mode 100644 (file)
index 0000000..3590bb9
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+public final class UniverseIdentifier extends AbstractIdentifier<UniverseIdentifier> {
+       public static final UniverseIdentifier L3_PACKET_TOPOLOGY = new UniverseIdentifier(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
+       public static final UniverseIdentifier L1_OPTICAL_TOPOLOGY = new UniverseIdentifier(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 });
+
+       private static final long serialVersionUID = 1L;
+       private final byte[] value;
+
+       public UniverseIdentifier(final byte[] value) {
+               this.value = value;
+       }
+
+       @Override
+       protected byte[] getBytes() {
+               return value;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("value", ByteArray.toHexString(value, "."));
+       }
+}
+
diff --git a/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/UnnumberedLinkIdentifier.java b/bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/UnnumberedLinkIdentifier.java
new file mode 100644 (file)
index 0000000..86b7175
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+/**
+ * Identifier class for Unnumbered Links, as defined by
+ * <a href="http://tools.ietf.org/html/rfc4202">RFC 4202</a>. Note that the
+ * class naming is a deliberate misnomer.
+ */
+public final class UnnumberedLinkIdentifier implements Comparable<UnnumberedLinkIdentifier>, InterfaceIdentifier {
+       private static final long serialVersionUID = -8301403294494612786L;
+       private final long value;
+
+       /**
+        * Create a new unnumbered link identifier.
+        *
+        * @param value Raw link identifier, has to be in range 1-4294967295
+        * @throws IllegalArgumentException when value is outside of allowed range
+        */
+       public UnnumberedLinkIdentifier(final long value) {
+               if (value < 1 || value > 4294967295L)
+                       throw new IllegalArgumentException("Unsupported identifier value");
+               this.value = value;
+       }
+
+       /**
+        * Returns raw link identifier value.
+        *
+        * @return value Raw link identifier value
+        */
+       public long getValue() {
+               return  this.value;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (int) (this.value ^ (this.value >>> 32));
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final UnnumberedLinkIdentifier other = (UnnumberedLinkIdentifier) obj;
+               if (this.value != other.value)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public int compareTo(final UnnumberedLinkIdentifier other) {
+               if (this == other)
+                       return 0;
+               if (other == null)
+                       return 1;
+               if (this.value < other.value)
+                       return -1;
+               if (this.value > other.value)
+                       return 1;
+               return 0;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("UnnumberedLinkIdentifier [value=");
+               builder.append(this.value);
+               builder.append("]");
+               return builder.toString();
+       }
+}
+
+
diff --git a/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/AdministrativeGroupTest.java b/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/AdministrativeGroupTest.java
new file mode 100644 (file)
index 0000000..69d4e5b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import static org.hamcrest.core.IsNot.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class AdministrativeGroupTest {
+
+       @Test
+       public void testOverflows() {
+               try {
+                       new AdministrativeGroup(-2);
+                       fail("Constructor successful unexpectedly");
+               } catch(IllegalArgumentException e) {}
+               try {
+                       new AdministrativeGroup(4294967296L);
+                       fail("Constructor successful unexpectedly");
+               } catch(IllegalArgumentException e) {}
+       }
+
+       @Test
+       public void testGetValue() {
+               AdministrativeGroup ag = new AdministrativeGroup(12345);
+               assertEquals(12345, ag.getValue());
+       }
+
+       @Test
+       public void testHashCode() {
+               AdministrativeGroup ag1 = new AdministrativeGroup(4321);
+               AdministrativeGroup ag2 = new AdministrativeGroup(4321);
+               assertEquals(ag1.hashCode(), ag2.hashCode());
+       }
+
+       @Test
+       public void testEquals() {
+               AdministrativeGroup ag1 = new AdministrativeGroup(4321);
+               AdministrativeGroup ag2 = ag1;
+               assertEquals(ag1, ag2);
+               assertEquals(ag1, new AdministrativeGroup(4321));
+               assertNotNull(ag1);
+               assertThat(ag1, not(new Object()));
+               assertThat(ag1, not(new AdministrativeGroup(5432)));
+               assertFalse(ag1.equals(null));
+               assertFalse(ag1.equals(new Object()));
+       }
+
+       @Test
+       public void testCompareTo(){
+               AdministrativeGroup a1 = new AdministrativeGroup(10);
+               AdministrativeGroup a2 = new AdministrativeGroup(5);
+               AdministrativeGroup a3 = new AdministrativeGroup(10);
+               assertTrue(a1.compareTo(a2) > 0);
+               assertTrue(a2.compareTo(a1) < 0);
+               assertTrue(a1.compareTo(a3) == 0);
+       }
+
+}
diff --git a/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/AreaIdentifierTest.java b/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/AreaIdentifierTest.java
new file mode 100644 (file)
index 0000000..6d83237
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class AreaIdentifierTest {
+
+       private AreaIdentifier identifier;
+
+       @Before
+       public void init() {
+               final byte[] id = new byte[] {10,0,0,1};
+               this.identifier = new AreaIdentifier(id);
+       }
+
+
+       @Test(expected=IllegalArgumentException.class)
+       public void testLinkAreaIdentifier() {
+               final byte[] id = new byte[] {10, 90, 13, 9, 3};
+               new AreaIdentifier(id);
+       }
+
+       @Test
+       public void testGetBytes() {
+               final byte[] id = new byte[] {10,0,0,1};
+               assertArrayEquals(id, this.identifier.getBytes());
+       }
+
+       @Test
+       public void testHashCode() {
+               final byte[] id1 = new byte[] {10,0,0,1};
+               final AreaIdentifier testIdentifier1 = new AreaIdentifier(id1);
+               assertEquals(this.identifier.hashCode(), testIdentifier1.hashCode());
+
+               final byte[] id2 = new byte[] {10,0,0,2};
+               final AreaIdentifier testIdentifier2 = new AreaIdentifier(id2);
+               assertThat(this.identifier.compareTo(testIdentifier2), not(equalTo(0)));
+       }
+
+       @Test
+       public void testEquals() {
+               assertThat(this.identifier, not(new Object()));
+
+               final byte[] id = new byte[] {10,0,0,1};
+               final AreaIdentifier testIdentifier = new AreaIdentifier(id);
+               assertEquals(this.identifier, testIdentifier);
+       }
+
+       @Test
+       public void testCompareTo() {
+               final byte[] id1 = new byte[] {10,0,0,1};
+               final AreaIdentifier testIdentifier1 = new AreaIdentifier(id1);
+               assertEquals(0, this.identifier.compareTo(testIdentifier1));
+
+               final byte[] id2 = new byte[] {10,0,0,2};
+               final AreaIdentifier testIdentifier2 = new AreaIdentifier(id2);
+               assertThat(this.identifier.compareTo(testIdentifier2), not(equalTo(0)));
+       }
+
+       @Test
+       public void testToString(){
+               final byte[] id1 = new byte[] {10,0,0,1};
+               final AreaIdentifier l1 = new AreaIdentifier(id1);
+               final String s1 = "AreaIdentifier{id=0a.00.00.01}";
+               assertEquals(s1, l1.toString());
+       }
+
+}
diff --git a/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/ISISAreaIdentifierTest.java b/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/ISISAreaIdentifierTest.java
new file mode 100644 (file)
index 0000000..1b73c87
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ISISAreaIdentifierTest {
+
+       private ISISAreaIdentifier identifier;
+
+       @Before
+       public void init() {
+               final byte[] id = new byte[] { 10, 0, 0, 1 };
+               this.identifier = new ISISAreaIdentifier(id);
+       }
+
+       @Test
+       public void testOverflows() {
+               try {
+                       new ISISAreaIdentifier(new byte[] {});
+                       fail("Constructor successful unexpectedly");
+               } catch (final IllegalArgumentException e) {
+               }
+               try {
+                       new ISISAreaIdentifier(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2 });
+                       fail("Constructor successful unexpectedly");
+               } catch (final IllegalArgumentException e) {
+               }
+       }
+
+       @Test
+       public void testGetBytes() {
+               assertArrayEquals(new byte[] { 10, 0, 0, 1 }, this.identifier.getBytes());
+       }
+
+       @Test
+       public void testHashCode() {
+               final byte[] id1 = new byte[] { 10, 0, 0, 1 };
+               final ISISAreaIdentifier testIdentifier1 = new ISISAreaIdentifier(id1);
+               assertEquals(testIdentifier1.hashCode(), this.identifier.hashCode());
+
+               final byte[] id2 = new byte[] { 10, 0, 0, 2 };
+               final ISISAreaIdentifier testIdentifier2 = new ISISAreaIdentifier(id2);
+               assertThat(testIdentifier2.hashCode(), not(equalTo(this.identifier.hashCode())));
+       }
+
+       @Test
+       public void testEqualsObject() {
+               assertThat(this.identifier, not(new Object()));
+
+               final byte[] id = new byte[] { 10, 0, 0, 1 };
+               final ISISAreaIdentifier testIdentifier = new ISISAreaIdentifier(id);
+               assertEquals(this.identifier, testIdentifier);
+       }
+
+       @Test
+       public void testCompareTo() {
+               final byte[] id1 = new byte[] { 10, 0, 0, 1 };
+               final ISISAreaIdentifier testIdentifier1 = new ISISAreaIdentifier(id1);
+               assertEquals(0, this.identifier.compareTo(testIdentifier1));
+
+               final byte[] id2 = new byte[] { 10, 0, 0, 2 };
+               final ISISAreaIdentifier testIdentifier2 = new ISISAreaIdentifier(id2);
+               assertThat(this.identifier.compareTo(testIdentifier2), not(equalTo(0)));
+       }
+
+       @Test(expected = NullPointerException.class)
+       public void testIllegalArgument() {
+               new ISISAreaIdentifier(null);
+       }
+
+       @Test
+       public void testToString() {
+               assertEquals("ISISAreaIdentifier{id=0a.00.00.01}", this.identifier.toString());
+               final ISISAreaIdentifier id = new ISISAreaIdentifier(new byte[] { 1 });
+               assertEquals("ISISAreaIdentifier{id=01}", id.toString());
+       }
+}
diff --git a/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/LinkAnchorTest.java b/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/LinkAnchorTest.java
new file mode 100644 (file)
index 0000000..60607e1
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+
+public class LinkAnchorTest {
+
+       @Test
+       public void test() {
+               try {
+                       new LinkAnchor(null, null);
+               } catch (final NullPointerException e) {
+                       assertEquals("Can not create link anchor with null node identifier.", e.getMessage());
+               }
+
+               final LinkAnchor la1 = new LinkAnchor(NodeIdentifierFactory.localIdentifier(new OSPFRouterIdentifier(new byte[] { 1, 2, 3, 4 })), IPv6InterfaceIdentifier.forString("2001:db8:85a3::8a2e:370:7334"));
+
+               final LinkAnchor la2 = new LinkAnchor(NodeIdentifierFactory.localIdentifier(new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] {
+                               1, 2, 3, 4, 5, 6 }))), null);
+
+               final LinkAnchor la3 = new LinkAnchor(NodeIdentifierFactory.localIdentifier(new OSPFRouterIdentifier(new byte[] { 1, 2, 3, 4 })), IPv6InterfaceIdentifier.forString("2001:db8:85a3::8a2e:370:7334"));
+
+               assertNotSame(la1, la2);
+               assertNotSame(la1.hashCode(), la2.hashCode());
+
+               assertEquals(la1, la3);
+               assertEquals(la1.toString(), la3.toString());
+               assertEquals(la1.getNodeIdentifier(), la3.getNodeIdentifier());
+
+               assertNull(la2.getInterfaceIdentifier());
+       }
+
+       @Test
+       public void testEnums() throws UnknownHostException {
+               assertEquals(MPLSProtocol.LDP.toString(), "LDP");
+               assertEquals(LinkProtectionType.ENHANCED.toString(), "ENHANCED");
+
+               final InterfaceIdentifier ii1 = new IPv6InterfaceIdentifier(new IPv6Address(InetAddress.getByName("2001:db8:85a3::8a2e:370:7334")));
+               final InterfaceIdentifier ii2 = new IPv6InterfaceIdentifier(new IPv6Address(InetAddress.getByName("2001:db8:85a3::8a2e:370:7335")));
+
+               assertEquals(-1, ((IPv6InterfaceIdentifier) ii1).compareTo((IPv6InterfaceIdentifier) ii2));
+               assertEquals(0, ((IPv6InterfaceIdentifier) ii1).compareTo((IPv6InterfaceIdentifier) ii1));
+
+               assertNotSame(ii1, ii2);
+
+               assertNotNull(((IPv6InterfaceIdentifier) ii1).getValue());
+
+               try {
+                       new IPv4InterfaceIdentifier(null);
+               } catch (final NullPointerException e) {
+                       assertEquals("Unsupported identifier value", e.getMessage());
+               }
+
+               try {
+                       new IPv6InterfaceIdentifier(null);
+               } catch (final NullPointerException e) {
+                       assertEquals("Unsupported identifier value", e.getMessage());
+               }
+
+               final InterfaceIdentifier ip1 = new IPv4InterfaceIdentifier(new IPv4Address(InetAddress.getByName("127.0.0.1")));
+               final InterfaceIdentifier ip2 = new IPv4InterfaceIdentifier(new IPv4Address(InetAddress.getByName("127.0.0.2")));
+
+               assertEquals(-1, ((IPv4InterfaceIdentifier) ip1).compareTo((IPv4InterfaceIdentifier) ip2));
+               assertEquals(0, ((IPv4InterfaceIdentifier) ip1).compareTo((IPv4InterfaceIdentifier) ip1));
+
+               assertNotSame(ip1, ip2);
+
+               assertNotNull(((IPv4InterfaceIdentifier) ip1).getValue());
+       }
+}
diff --git a/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/LinkIdentifierTest.java b/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/LinkIdentifierTest.java
new file mode 100644 (file)
index 0000000..1dff482
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4;
+
+public class LinkIdentifierTest {
+
+       @Test
+       public void test() {
+
+               final LinkAnchor a = new LinkAnchor(NodeIdentifierFactory.localIdentifier(new IPv4RouterIdentifier(IPv4.FAMILY.addressForString("12.51.8.4"))),
+                               IPv4InterfaceIdentifier.forString("12.51.8.4"));
+
+               final LinkAnchor b = new LinkAnchor(NodeIdentifierFactory.localIdentifier(new IPv4RouterIdentifier(IPv4.FAMILY.addressForString("12.51.8.10"))),
+                               IPv4InterfaceIdentifier.forString("12.51.8.10"));
+
+               final LinkIdentifier l1 = new LinkIdentifier(new TopologyIdentifier(5), a, b);
+
+               final LinkIdentifier l11 = new LinkIdentifier(new TopologyIdentifier(5), a, b);
+
+               final LinkIdentifier l2 = new LinkIdentifier(new TopologyIdentifier(5), b, a);
+
+               assertNotSame(l1, l2);
+
+               assertEquals(l1, l11);
+
+               assertNotSame(l1.getLocalAnchor(), l2.getLocalAnchor());
+
+               assertEquals(l1.getLocalAnchor(), l2.getRemoteAnchor());
+
+               assertNotNull(l1.getTopology());
+
+               assertEquals(l1.hashCode(), l11.hashCode());
+
+               assertEquals(l1.toString(), l11.toString());
+       }
+}
diff --git a/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/NodeIdentifierTest.java b/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/NodeIdentifierTest.java
new file mode 100644 (file)
index 0000000..8ab3fdb
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+
+public class NodeIdentifierTest {
+       private final NodeIdentifierFactory f = new NodeIdentifierFactory(new ASNumber(25600, 0), null, null);
+
+       @Test
+       public void testHashCodeEquals() {
+               final NodeIdentifier id1 = this.f.identifierForRouter(new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] { 0x22, 0x22,
+                               0x22, 0x22, 0x22, 0x22 })));
+               final NodeIdentifier id2 = this.f.identifierForRouter(new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] { 0x22, 0x22,
+                               0x22, 0x22, 0x22, 0x22 })));
+               final NodeIdentifier id3 = this.f.identifierForRouter(new IPv4RouterIdentifier(IPv4.FAMILY.addressForString("192.168.1.5")));
+               final NodeIdentifier id4 = this.f.identifierForRouter(new IPv6RouterIdentifier(IPv6.FAMILY.addressForString("2001:db8:85a3::8a2e:370:7334")));
+
+               assertEquals("HashCodes should be equal", id1.hashCode(), id2.hashCode());
+               assertEquals("toString should be equal", id1.toString(), id2.toString());
+               assertEquals(id1, id2);
+
+               assertNotSame(id1, id3);
+               assertNotSame(id3, id4);
+       }
+
+       @Test
+       public void testIPv4RouterIdentifier() {
+               try {
+                       new IPv4RouterIdentifier(null);
+                       fail("Nullable IPv4RouterIdentifier");
+               } catch (final NullPointerException e) {
+                       assertEquals("Address may not be null", e.getMessage());
+               }
+
+               final IPv4RouterIdentifier ip1 = new IPv4RouterIdentifier(IPv4.FAMILY.addressForString("127.0.0.1"));
+               final IPv4RouterIdentifier ip2 = new IPv4RouterIdentifier(IPv4.FAMILY.addressForString("127.0.0.1"));
+
+               assertEquals(ip1, ip2);
+       }
+
+       @Test
+       public void testIPv6RouterIdentifier() {
+               try {
+                       new IPv6RouterIdentifier(null);
+                       fail("Nullable IPv6RouterIdentifier");
+               } catch (final NullPointerException e) {
+                       assertEquals("Address may not be null", e.getMessage());
+               }
+
+               final IPv6RouterIdentifier ip1 = new IPv6RouterIdentifier(IPv6.FAMILY.addressForString("2001:db8:85a3::8a2e:370:7334"));
+               final IPv6RouterIdentifier ip2 = new IPv6RouterIdentifier(IPv6.FAMILY.addressForString("2001:db8:85a3::8a2e:370:7334"));
+
+               assertEquals(ip1, ip2);
+       }
+
+       @Test
+       public void testISISRouterIdentifier() {
+               final ISISRouterIdentifier is1 = new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }));
+               final ISISRouterIdentifier is2 = new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }));
+
+               assertEquals(is1, is2);
+       }
+
+       @Test
+       public void testOSPFNodeIdentifier() {
+               try {
+                       new OSPFRouterIdentifier(null);
+                       fail("Nullable Router Identifier!");
+               } catch (final NullPointerException e) {
+                       assertEquals("Router identifier may not be null", e.getMessage());
+               }
+
+               try {
+                       new OSPFRouterIdentifier(new byte[] { 5 });
+                       fail("Wrong length of OSPF Router Identifier!");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Router identifier must be 4 bytes long", e.getMessage());
+               }
+
+               final OSPFRouterIdentifier os1 = new OSPFRouterIdentifier(new byte[] { 5, 5, 5, 5 });
+               final OSPFRouterIdentifier os2 = new OSPFRouterIdentifier(new byte[] { 5, 5, 5, 5 });
+
+               assertEquals(os1, os2);
+       }
+}
diff --git a/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/SharedRiskLinkGroupTest.java b/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/SharedRiskLinkGroupTest.java
new file mode 100644 (file)
index 0000000..b2d1d1d
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+
+public class SharedRiskLinkGroupTest {
+
+       @Test
+       public void testOverflows() {
+               try {
+                       new SharedRiskLinkGroup(-2);
+                       fail("Constructor successful unexpectedly");
+               } catch(IllegalArgumentException e) {}
+               try {
+                       new SharedRiskLinkGroup(4294967296L);
+                       fail("Constructor successful unexpectedly");
+               } catch(IllegalArgumentException e) {}
+       }
+
+       @Test
+       public void testGetValue() {
+               SharedRiskLinkGroup group = new SharedRiskLinkGroup(252);
+               assertEquals(252, group.getValue());
+       }
+
+       @Test
+       public void testHashCodeEquals() {
+               SharedRiskLinkGroup group1 = new SharedRiskLinkGroup(252);
+               SharedRiskLinkGroup group2 = new SharedRiskLinkGroup(252);
+               SharedRiskLinkGroup group3 = new SharedRiskLinkGroup(987);
+               SharedRiskLinkGroup group4 = group3;
+
+               assertThat(group1.hashCode(), equalTo(group2.hashCode()));
+               assertThat(group1.hashCode(), not(equalTo(group3.hashCode())));
+
+               assertThat(group1, equalTo(group2));
+               assertThat(group1, not(equalTo((group3))));
+               assertThat(group3, equalTo(group4));
+               assertNotNull(group1);
+               assertThat(group1, not(new Object()));
+       }
+
+       @Test
+       public void testCompareTo(){
+               SharedRiskLinkGroup s1 = new SharedRiskLinkGroup(123);
+               SharedRiskLinkGroup s2 = s1;
+               SharedRiskLinkGroup s3 = new SharedRiskLinkGroup(158);
+               assertTrue(s1.compareTo(s2) == 0);
+               assertTrue(s1.compareTo(s3) < 0);
+               assertTrue(s3.compareTo(s1) > 0);
+       }
+
+       @Test
+       public void testEquals(){
+               SharedRiskLinkGroup s1 = new SharedRiskLinkGroup(123);
+               SharedRiskLinkGroup s2 = s1;
+               SharedRiskLinkGroup s3 = new SharedRiskLinkGroup(158);
+               assertFalse(s1.equals(null));
+               assertFalse(s1.equals(new Object()));
+               assertTrue(s1.equals(s2));
+               assertFalse(s1.equals(s3));
+       }
+
+}
diff --git a/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/TopologyIdentifierTest.java b/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/TopologyIdentifierTest.java
new file mode 100644 (file)
index 0000000..6d14adc
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class TopologyIdentifierTest {
+
+       private TopologyIdentifier identifier;
+
+       @Before
+       public void init() {
+               this.identifier = new TopologyIdentifier(23);
+       }
+
+       @Test
+       public void testLinkAreaIdentifier() {
+               try {
+                       new TopologyIdentifier(4096);
+               } catch (final Exception e) {
+                       assertTrue(e instanceof IllegalArgumentException);
+               }
+               try {
+                       new TopologyIdentifier(-2);
+               } catch (final Exception e) {
+                       assertTrue(e instanceof IllegalArgumentException);
+               }
+
+       }
+
+       @Test
+       public void testGetId() {
+               assertEquals(23, this.identifier.getId());
+       }
+
+       @Test
+       public void testHashCode() {
+               final TopologyIdentifier testIdentifier1 = new TopologyIdentifier(23);
+               assertEquals(this.identifier.hashCode(), testIdentifier1.hashCode());
+
+               final TopologyIdentifier testIdentifier2 = new TopologyIdentifier(24);
+               assertThat(this.identifier.compareTo(testIdentifier2), not(equalTo(0)));
+       }
+
+       @Test
+       public void testEquals() {
+               assertThat(this.identifier, not(new Object()));
+
+               final TopologyIdentifier testIdentifier = new TopologyIdentifier(23);
+               assertEquals(this.identifier, testIdentifier);
+       }
+
+       @Test
+       public void testCompareTo() {
+               final TopologyIdentifier testIdentifier1 = new TopologyIdentifier(23);
+               assertEquals(0, this.identifier.compareTo(testIdentifier1));
+
+               final TopologyIdentifier testIdentifier2 = new TopologyIdentifier(34);
+               assertThat(this.identifier.compareTo(testIdentifier2), not(equalTo(0)));
+       }
+
+       @Test
+       public void testToString() {
+               assertEquals("TopologyIdentifier{id=23}", this.identifier.toString());
+               final TopologyIdentifier id = new TopologyIdentifier(3);
+               assertEquals("TopologyIdentifier{id=3}", id.toString());
+       }
+}
diff --git a/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/TopologyNodeInformationTest.java b/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/TopologyNodeInformationTest.java
new file mode 100644 (file)
index 0000000..b150499
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class TopologyNodeInformationTest {
+
+       @Test
+       public void test() {
+               TopologyNodeInformation nodeInfo1 = new TopologyNodeInformation(true, true);
+               TopologyNodeInformation nodeInfo2 = new TopologyNodeInformation(false, false);
+               assertTrue(nodeInfo1.isAttached());
+               assertTrue(nodeInfo1.isOverloaded());
+               assertFalse(nodeInfo2.isAttached());
+               assertFalse(nodeInfo2.isOverloaded());
+       }
+
+       @Test
+       public void testEquals(){
+               TopologyNodeInformation t1 =  new TopologyNodeInformation(true, true);
+               TopologyNodeInformation t2 = t1;
+               TopologyNodeInformation t3 = new TopologyNodeInformation(true, false);
+               assertEquals(t1, t2);
+               assertEquals(t1,  new TopologyNodeInformation(true, true));
+               assertFalse(t1.equals(t3));
+               assertFalse(t1.equals(null));
+               assertFalse(t1.equals(new Object()));
+       }
+
+       @Test
+       public void testHashCode(){
+               TopologyNodeInformation t1 = new TopologyNodeInformation(true, false);
+               TopologyNodeInformation t2 = new TopologyNodeInformation(true, false);
+               assertEquals(t1.hashCode(), t2.hashCode());
+       }
+
+       @Test
+       public void testToString(){
+               TopologyNodeInformation t1 = new TopologyNodeInformation(true, false);
+               String s = "TopologyNodeInformation [attached=" + t1.isAttached() + ", overloaded=" + t1.isOverloaded() + "]";
+               assertEquals(s, t1.toString());
+       }
+}
diff --git a/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/UnnumberedLinkIdentifierTest.java b/bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/UnnumberedLinkIdentifierTest.java
new file mode 100644 (file)
index 0000000..1a77c4e
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.linkstate;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class UnnumberedLinkIdentifierTest {
+
+       private UnnumberedLinkIdentifier unnumberedId;
+
+       @Before
+       public void init() {
+               this.unnumberedId = new UnnumberedLinkIdentifier(256);
+       }
+
+       @Test
+       public void testOverflows() {
+               try {
+                       new UnnumberedLinkIdentifier(-2);
+                       fail("Constructor successful unexpectedly");
+               } catch(final IllegalArgumentException e) {}
+               try {
+                       new UnnumberedLinkIdentifier(4294967296L);
+                       fail("Constructor successful unexpectedly");
+               } catch(final IllegalArgumentException e) {}
+       }
+
+       @Test
+       public void testGetValue() {
+               assertEquals(256L, this.unnumberedId.getValue());
+       }
+
+       /**
+        * Test hashcode(), equals(), compareTo()
+        */
+       @Test
+       public void test() {
+               final UnnumberedLinkIdentifier testId1 = this.unnumberedId;
+               final UnnumberedLinkIdentifier testId2 = new UnnumberedLinkIdentifier(256);
+               final UnnumberedLinkIdentifier testId3 = new UnnumberedLinkIdentifier(951);
+
+               assertEquals(testId1.hashCode(), testId2.hashCode());
+               assertThat(testId2.hashCode(), not(equalTo(testId3.hashCode())));
+
+               assertEquals(testId1, testId2);
+               assertEquals(testId1.toString(), testId2.toString());
+               assertThat(testId1, not(equalTo(testId3)));
+               assertEquals(this.unnumberedId, testId1);
+               assertNotNull(this.unnumberedId);
+               assertThat(this.unnumberedId, not(equalTo(new Object())));
+
+               assertEquals(0, testId1.compareTo(testId2));
+               assertEquals(0, this.unnumberedId.compareTo(testId1));
+               assertEquals(1, this.unnumberedId.compareTo(null));
+               assertThat(testId2.compareTo(testId3), not(equalTo(0)));
+               assertThat(testId3.compareTo(testId1), not(equalTo(0)));
+       }
+
+}
diff --git a/bgp/parser-api/.gitignore b/bgp/parser-api/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/bgp/parser-api/.project b/bgp/parser-api/.project
new file mode 100644 (file)
index 0000000..44d4263
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>bgp-parser-api</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bgp/parser-api/pom.xml b/bgp/parser-api/pom.xml
new file mode 100644 (file)
index 0000000..9b9f769
--- /dev/null
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>bgp-parent</artifactId>
+               <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-parser-api</artifactId>
+       <description>BGP Parser API</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>framework</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-linkstate</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-api</artifactId>
+                       <version>${slf4j.version}</version>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Import-Package>
+                                                       org.opendaylight.protocol.bgp.concepts, 
+                                                       org.opendaylight.protocol.concepts,
+                                                       org.opendaylight.protocol.framework,
+                                                       org.opendaylight.protocol.concepts, 
+                                                       org.opendaylight.protocol.util,
+                                                       com.google.common.primitives, 
+                                                       com.google.common.collect, 
+                                                       org.opendaylight.protocol.bgp.linkstate,
+                                                       com.google.common.base,
+                                                       com.google.guava,
+                                                       org.slf4j,
+                                               </Import-Package>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.bgp.parser,
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>${checkstyle.version}</version>
+                               <configuration>
+                                       <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+                                       <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>BGP-PARSER-API Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/AbstractBGPObjectState.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/AbstractBGPObjectState.java
new file mode 100644 (file)
index 0000000..b03b2d5
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import com.google.common.base.Objects.ToStringHelper;
+
+public abstract class AbstractBGPObjectState<T extends NetworkObjectState> extends BaseBGPObjectState {
+       private static final long serialVersionUID = 1L;
+       private final T objectState;
+
+       public AbstractBGPObjectState(final BaseBGPObjectState orig, final T objectState) {
+               super(orig);
+               this.objectState = objectState;
+       }
+
+       protected AbstractBGPObjectState(final AbstractBGPObjectState<T> orig) {
+               super(orig);
+               this.objectState = orig.objectState;
+       }
+
+       public final T getObjectState() {
+               return this.objectState;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("objectState", this.objectState);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.objectState == null) ? 0 : this.objectState.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final AbstractBGPObjectState<?> other = (AbstractBGPObjectState<?>) obj;
+               if (this.objectState == null) {
+                       if (other.objectState != null)
+                               return false;
+               } else if (!this.objectState.equals(other.objectState))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPDocumentedException.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPDocumentedException.java
new file mode 100644 (file)
index 0000000..a75aeb7
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DocumentedException;
+
+/**
+ * There are several errors documented in RFC4271 or in draft, that have specific meaning for the BGP. This exception is
+ * used, when any of those errors occurs.
+ */
+public final class BGPDocumentedException extends DocumentedException {
+
+       private static final long serialVersionUID = -6212702584439430736L;
+
+       private static final Logger logger = LoggerFactory.getLogger(BGPDocumentedException.class);
+
+       private final BGPError error;
+
+       private final byte[] data;
+
+       /**
+        * Used when an error occurred that is described in rfc or draft.
+        * 
+        * @param message message bound with this exception
+        * @param error specific documented error
+        */
+       public BGPDocumentedException(final String message, final BGPError error) {
+               this(message, error, null);
+       }
+
+       /**
+        * Used when an error occurred that is described in rfc or draft.
+        * 
+        * @param message message bound with this exception
+        * @param error specific documented error
+        * @param data data associated with the error
+        */
+       public BGPDocumentedException(final String message, final BGPError error, final byte[] data) {
+               super(message);
+               this.error = error;
+               this.data = data;
+               logger.error("Error = " + error, this);
+       }
+
+       /**
+        * Returns specific documented error.
+        * 
+        * @return documented error
+        */
+       public BGPError getError() {
+               return this.error;
+       }
+
+       /**
+        * Returns data associated with this error.
+        * 
+        * @return byte array data
+        */
+       public byte[] getData() {
+               return this.data;
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPError.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPError.java
new file mode 100644 (file)
index 0000000..6049edf
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+/**
+ * Possible errors from implemented RFCs and drafts. Each error consists of error code and error subcode (code/subcode
+ * in comments).
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.5">BGP Notification Message</a>
+ */
+public enum BGPError {
+       /**
+        * Connection Not Synchronized. 1/1
+        */
+       CONNECTION_NOT_SYNC,
+       /**
+        * Bad Message Length. 1/2
+        */
+       BAD_MSG_LENGTH,
+       /**
+        * Bad Message Type. 1/3
+        */
+       BAD_MSG_TYPE,
+       /**
+        * Unspecific Open Message error.
+        */
+       UNSPECIFIC_OPEN_ERROR,
+       /**
+        * Unsupported Version Number. 2/1
+        */
+       VERSION_NOT_SUPPORTED,
+       /**
+        * Bad Peer AS. 2/2
+        */
+       BAD_PEER_AS,
+       /**
+        * Bad BGP Identifier. 2/3
+        */
+       BAD_BGP_ID,
+       /**
+        * Unsupported Optional Parameter. 2/4
+        */
+       OPT_PARAM_NOT_SUPPORTED,
+       /**
+        * Unacceptable Hold Time. 2/6
+        */
+       HOLD_TIME_NOT_ACC,
+       /**
+        * Malformed Attribute List. 3/1
+        */
+       MALFORMED_ATTR_LIST,
+       /**
+        * Unrecognized Well-known Attribute. 3/2
+        */
+       WELL_KNOWN_ATTR_NOT_RECOGNIZED,
+       /**
+        * Missing Well-known Attribute. 3/3
+        */
+       WELL_KNOWN_ATTR_MISSING,
+       /**
+        * Attribute Flags Error. 3/4
+        */
+       ATTR_FLAGS_MISSING,
+       /**
+        * Attribute Length Error. 3/5
+        */
+       ATTR_LENGTH_ERROR,
+       /**
+        * Invalid ORIGIN Attribute. 3/6
+        */
+       ORIGIN_ATTR_NOT_VALID,
+       /**
+        * Invalid NEXT_HOP Attribute. 3/8
+        */
+       NEXT_HOP_NOT_VALID,
+       /**
+        * Optional Attribute Error. 3/9
+        */
+       OPT_ATTR_ERROR,
+       /**
+        * Invalid Network Field. 3/10
+        */
+       NETWORK_NOT_VALID,
+       /**
+        * Malformed AS_PATH. 3/11
+        */
+       AS_PATH_MALFORMED,
+       /**
+        * Hold Timer Expired. 4/0
+        */
+       HOLD_TIMER_EXPIRED,
+       /**
+        * Finite State Machine Error. 5/0
+        */
+       FSM_ERROR,
+       /**
+        * Cease. 6/0
+        */
+       CEASE
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPLink.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPLink.java
new file mode 100644 (file)
index 0000000..e1f751e
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+
+/**
+ * Interface exposing the attributes of a BGPLink.
+ */
+public interface BGPLink extends BGPObject {
+       @Override
+       public BGPLinkState currentState();
+
+       /**
+        * Returns object Link Identifier describing this link.
+        * 
+        * @return Link Identifier
+        */
+       public LinkIdentifier getLinkIdentifier();
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPLinkState.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPLinkState.java
new file mode 100644 (file)
index 0000000..03b6060
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+
+public final class BGPLinkState extends AbstractBGPObjectState<NetworkLinkState> {
+       private static final long serialVersionUID = 1L;
+
+       public BGPLinkState(BaseBGPObjectState orig, NetworkLinkState linkState) {
+               super(orig, linkState);
+       }
+
+       protected BGPLinkState(BGPLinkState orig) {
+               super(orig, orig.getObjectState());
+       }
+
+       @Override
+       protected BGPLinkState newInstance() {
+               return new BGPLinkState(this);
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPMessage.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPMessage.java
new file mode 100644 (file)
index 0000000..416d9c6
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.framework.ProtocolMessage;
+
+/**
+ * Basic structure for BGP Message. There is not other common feature than the serialization.
+ */
+public interface BGPMessage extends ProtocolMessage {
+
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPMessageHeader.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPMessageHeader.java
new file mode 100644 (file)
index 0000000..c629ea7
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Representation of BGP Message Header. Includes methods for parsing and serializing header.
+ * Length field represents the length of the message including the length of its header.
+ */
+public class BGPMessageHeader implements ProtocolMessageHeader {
+
+       public static final Logger logger = LoggerFactory.getLogger(BGPMessageHeader.class);
+
+       /**
+        * BGP message header fixed length (in bytes)
+        */
+       public static final int COMMON_HEADER_LENGTH = 19;
+
+       private static final int MARKER_SIZE = 16;
+       private static final int LENGTH_SIZE = 2;
+       private static final int TYPE_OFFSET = MARKER_SIZE + LENGTH_SIZE;
+
+       private int type;
+       private int length;
+       private boolean parsed = false;
+
+       /**
+        * Creates message header.
+        */
+       public BGPMessageHeader() {
+
+       }
+
+       /**
+        * Creates message header with given attributes.
+        * @param type int
+        * @param length int
+        */
+       public BGPMessageHeader(final int type, final int length) {
+               this.type = type;
+               this.length = length;
+       }
+
+       /**
+        * Creates a BGP Message Header from given byte array.
+        *
+        * @param bytes byte array to be parsed
+        * @return BGP Message Header
+        */
+       public BGPMessageHeader fromBytes(final byte[] bytes) {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Array of bytes is mandatory");
+               //FIXME: how to send Notification message from this point?
+               //              final byte[] ones = new byte[MARKER_SIZE];
+               //              Arrays.fill(ones, (byte)0xff);
+               //
+               //              if (Arrays.equals(bytes, ones))
+               //                      throw new BGPDocumentedException("Marker not set to ones.", BGPError.CONNECTION_NOT_SYNC);
+
+               logger.trace("Attempt to parse message header: {}", ByteArray.bytesToHexString(bytes));
+
+               if (bytes.length < COMMON_HEADER_LENGTH)
+                       throw new IllegalArgumentException("Too few bytes in passed array. Passed: " + bytes.length + ". Expected: >= " + COMMON_HEADER_LENGTH + ".");
+
+               this.length = ByteArray.bytesToInt(ByteArray.subByte(bytes, MARKER_SIZE, LENGTH_SIZE));
+
+               this.type = UnsignedBytes.toInt(bytes[TYPE_OFFSET]);
+
+               logger.trace("Message header was parsed. {}", this);
+               this.parsed = true;
+               return this;
+       }
+
+       /**
+        * Serializes this BGP Message header to byte array.
+        *
+        * @return byte array representation of this header
+        */
+       public byte[] toBytes() {
+               final byte[] retBytes = new byte[COMMON_HEADER_LENGTH];
+
+               Arrays.fill(retBytes, 0, MARKER_SIZE, (byte)0xff);
+
+               System.arraycopy(ByteArray.intToBytes(this.length), Integer.SIZE / Byte.SIZE - LENGTH_SIZE, retBytes, MARKER_SIZE, LENGTH_SIZE);
+
+               retBytes[TYPE_OFFSET] = (byte) this.type;
+
+               return retBytes;
+       }
+
+       /**
+        * Returns length presented in Length field of this header.
+        *
+        * @return length of the BGP message
+        */
+       public int getLength() {
+               return this.length;
+       }
+
+       /**
+        * Returns type presented in Type field of this header.
+        *
+        * @return type of the BGP message
+        */
+       public int getType() {
+               return this.type;
+       }
+
+       /**
+        * Return the state of the parsing of this header.
+        *
+        * @return the parsed true if the header was parsed false if the header was not parsed
+        */
+       public boolean isParsed() {
+               return this.parsed;
+       }
+
+       /**
+        * Marks parsing as not finished. There is no need for other classes to mark parsing as done, therefore calling this
+        * method will set parsing to unfinished.
+        */
+       public void setParsed() {
+               this.parsed = false;
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPMessageParser.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPMessageParser.java
new file mode 100644 (file)
index 0000000..ced4df8
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import java.io.Closeable;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+
+/**
+ * Parser for BGP Messages.
+ */
+public interface BGPMessageParser extends ProtocolMessageFactory, Closeable {
+
+       @Override
+       public BGPMessage parse(byte[] bytes, ProtocolMessageHeader msgHeader) throws DeserializerException, DocumentedException;
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPNode.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPNode.java
new file mode 100644 (file)
index 0000000..b6e7319
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+
+/**
+ * Interface exposing the attributes of a BGPNode.
+ */
+public interface BGPNode extends BGPObject {
+       @Override
+       public BGPNodeState currentState();
+
+       /**
+        * Returns object Node Identifier describing this node.
+        * 
+        * @return {@link NodeIdentifier}
+        */
+       public NodeIdentifier getNodeIdentifier();
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPNodeState.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPNodeState.java
new file mode 100644 (file)
index 0000000..b0eac58
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+
+public final class BGPNodeState extends AbstractBGPObjectState<NetworkNodeState> {
+       private static final long serialVersionUID = 1L;
+
+       public BGPNodeState(BaseBGPObjectState orig, NetworkNodeState nodeState) {
+               super(orig, nodeState);
+       }
+
+       protected BGPNodeState(BGPNodeState orig) {
+               super(orig, orig.getObjectState());
+       }
+
+       @Override
+       protected BGPNodeState newInstance() {
+               return new BGPNodeState(this);
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPParameter.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPParameter.java
new file mode 100644 (file)
index 0000000..2ddc785
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+/**
+ * Marker interface of each BGP Parameter. Currently we have only Capabilities parameter.
+ */
+public interface BGPParameter {
+
+       /**
+        * Returns fixed type of the parameter.
+        * 
+        * @return type of the parameter
+        */
+       public int getType();
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPParsingException.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPParsingException.java
new file mode 100644 (file)
index 0000000..8ac9f06
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+
+/**
+ *
+ * Used when something occurs during the parsing to get Update Message.
+ *
+ */
+public class BGPParsingException extends DeserializerException {
+
+       private static final long serialVersionUID = -6893285837086620580L;
+
+       private final String message;
+
+       /**
+        *
+        * @param err error message string.
+        */
+       public BGPParsingException(final String err) {
+               super(err);
+               this.message = err;
+       }
+
+       /**
+        *
+        * @param message exception message
+        * @param cause primary exception
+        */
+       public BGPParsingException(final String message, final Exception cause){
+               super(message, cause);
+               this.message = message;
+       }
+
+       /**
+        *
+        * @return error message.
+        */
+       public String getError() {
+               return this.message;
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPPrefix.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPPrefix.java
new file mode 100644 (file)
index 0000000..5900f35
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+
+/**
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-idr-ls-distribution-02#section-3.2">Figure 9: The IPv4/IPv6
+ *      Topology Prefix NLRI format</a>
+ * 
+ * @param <T> Network Address type of the prefix
+ */
+public interface BGPPrefix<T extends NetworkAddress<T>> extends BGPObject {
+       @Override
+       public BGPPrefixState currentState();
+
+       /**
+        * Return the Prefix Identifier.
+        * 
+        * @return Prefix Identifier
+        */
+       public PrefixIdentifier<T> getPrefixIdentifier();
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPPrefixState.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPPrefixState.java
new file mode 100644 (file)
index 0000000..12bcbbb
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+
+public final class BGPPrefixState extends AbstractBGPObjectState<NetworkPrefixState> {
+       private static final long serialVersionUID = 1L;
+
+       public BGPPrefixState(BaseBGPObjectState base, NetworkPrefixState prefixState) {
+               super(base, prefixState);
+       }
+
+       protected BGPPrefixState(BGPPrefixState orig) {
+               super(orig, orig.getObjectState());
+       }
+
+       @Override
+       protected BGPPrefixState newInstance() {
+               return new BGPPrefixState(this);
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPRoute.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPRoute.java
new file mode 100644 (file)
index 0000000..df8c055
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+
+import org.opendaylight.protocol.concepts.NamedObject;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ * A route is a unit of information that pairs a set of destinations with the attributes of a path to those
+ * destinations. The set of destinations are systems whose IP addresses are contained in one IP address prefix carried
+ * in the Network Layer Reachability Information (NLRI) field of an UPDATE message. The path is the information reported
+ * in the path attributes field of the same UPDATE message.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-1.1">Definition of Commonly Used Terms</a>
+ * @param <T> subtype of Network Address
+ */
+public interface BGPRoute<T extends NetworkAddress<T>> extends BGPObject, NamedObject<Prefix<T>> {
+       
+       @Override
+       public BGPRouteState<T> currentState();
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPRouteState.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPRouteState.java
new file mode 100644 (file)
index 0000000..0a49ddb
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+
+public final class BGPRouteState<T extends NetworkAddress<?>> extends AbstractBGPObjectState<NetworkRouteState<T>> {
+       private static final long serialVersionUID = 1L;
+
+       public BGPRouteState(BaseBGPObjectState orig, NetworkRouteState<T> routeState) {
+               super(orig, routeState);
+       }
+
+       protected BGPRouteState(BGPRouteState<T> orig) {
+               super(orig, orig.getObjectState());
+       }
+
+       @Override
+       protected BGPRouteState<T> newInstance() {
+               return new BGPRouteState<T>(this);
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPSession.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPSession.java
new file mode 100644 (file)
index 0000000..53bd9e3
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import java.io.Closeable;
+
+/**
+ * BGP Session represents the finite state machine in BGP, including timers and its purpose is to create a BGP
+ * connection between BGP speakers. Session is automatically started, when TCP connection is created, but can be stopped
+ * manually via close method of the Closeable interface.
+ * 
+ * If the session is up, it has to redirect messages to/from user. Handles also malformed messages and unknown requests.
+ */
+public interface BGPSession extends Closeable {
+       @Override
+       public void close();
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPSessionListener.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPSessionListener.java
new file mode 100644 (file)
index 0000000..76f618b
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+
+import org.opendaylight.protocol.framework.SessionListener;
+
+/**
+ * Listener that receives session informations from the session.
+ */
+public abstract class BGPSessionListener implements SessionListener {
+
+       /**
+        * Fired when an Update or a non-fatal Notification message is received.
+        * 
+        * @param message BGPMessage
+        */
+       public abstract void onMessage(BGPMessage message);
+
+       /**
+        * Fired when the session was established successfully.
+        * 
+        * @param remoteParams Peer address families which we accepted
+        */
+       public abstract void onSessionUp(Set<BGPTableType> remoteParams);
+
+       /**
+        * Fired when the session went down because of an IO error. Implementation should take care of closing underlying
+        * session.
+        * 
+        * @param session that went down
+        * @param e Exception that was thrown as the cause of session being down
+        */
+       public abstract void onSessionDown(BGPSession session, Exception e);
+
+       /**
+        * Fired when the session is terminated locally. The session has already been closed and transitioned to IDLE state.
+        * Any outstanding queued messages were not sent. The user should not attempt to make any use of the session.
+        * 
+        * @param cause the cause why the session went down
+        */
+       public abstract void onSessionTerminated(BGPError cause);
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPUpdateEvent.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPUpdateEvent.java
new file mode 100644 (file)
index 0000000..2d37917
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+/**
+ * Marker interface for events resulting from parsing of an BGP UPDATE message. An unfortunate twist in BGP spec makes
+ * use of a specially-crafted message to indicate that a per-AFI RIB has been completely synchronized.
+ * 
+ * Extends ProtocolMessage to allow parsing of BGP Update Messages in BGP listener.
+ */
+public interface BGPUpdateEvent extends BGPMessage {
+
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPUpdateMessage.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPUpdateMessage.java
new file mode 100644 (file)
index 0000000..ef015cd
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+
+
+/**
+ * 
+ * BGP Update Message contains two sets of Objects, ones that have to be removed from the topology and ones that need to
+ * be added. Although it is restricted to have the same object in both sets, the implementation needs to handle this
+ * kind of situation. Therefore, first step is to remove objects, then add the other set.
+ * 
+ */
+public interface BGPUpdateMessage extends BGPUpdateEvent, BGPMessage {
+       /**
+        * Objects that are identified with Identifiers in this set, need to be removed from topology.
+        * 
+        * @return set of identifiers of objects to be removed
+        */
+       public Set<?> getRemovedObjects();
+
+       /**
+        * Set of objects that need to be added to the topology wrapped in BGPObject that includes the identifier and its
+        * attributes.
+        * 
+        * @return set of BGPObjects to be added
+        */
+       public Set<BGPObject> getAddedObjects();
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPUpdateSynchronized.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPUpdateSynchronized.java
new file mode 100644 (file)
index 0000000..a5adc6e
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+
+/**
+ * Update event indicating that a RIB has reached initial synchronization. An instance of this interface is generated
+ * when the BGP UPDATE parser encounters such a marker message.
+ */
+public interface BGPUpdateSynchronized extends BGPUpdateEvent {
+       /**
+        * Identify which RIB has reached synchronization.
+        * 
+        * @return BGP table type
+        */
+       public BGPTableType getTableType();
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/message/BGPKeepAliveMessage.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/message/BGPKeepAliveMessage.java
new file mode 100644 (file)
index 0000000..af199a5
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.message;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+
+/**
+ * BGP KeepAlive message. Always empty.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.4">BGP KeepAlive message</a>
+ */
+public final class BGPKeepAliveMessage implements BGPMessage {
+
+       private static final long serialVersionUID = 5469664138660829255L;
+
+       /**
+        * Creates a BGP KeepAlive message.
+        */
+       public BGPKeepAliveMessage() {
+
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/message/BGPNotificationMessage.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/message/BGPNotificationMessage.java
new file mode 100644 (file)
index 0000000..7943aa3
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.message;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+
+
+/**
+ * Representation of BGPNotification message.
+ * 
+ * @see <a link="http://tools.ietf.org/html/rfc4271#section-4.5">BGP Notification Message</a>
+ */
+public final class BGPNotificationMessage implements BGPMessage {
+
+       private static final long serialVersionUID = -5860147919167775673L;
+
+       private final BGPError error;
+
+       private final byte[] data;
+
+       /**
+        * Creates a BGPNotification message with no data.
+        * 
+        * @param error cause
+        */
+       public BGPNotificationMessage(final BGPError error) {
+               this(error, null);
+       }
+
+       /**
+        * Creates a BGPNotification message with error cause and data.
+        * 
+        * @param error cause
+        * @param data associated with this message
+        */
+       public BGPNotificationMessage(final BGPError error, final byte[] data) {
+               super();
+               this.error = error;
+               this.data = data;
+       }
+
+       /**
+        * Returns BGPError contained in this message.
+        * 
+        * @return the error
+        */
+       public BGPError getError() {
+               return this.error;
+       }
+
+       /**
+        * Returns possible data associated with this message.
+        * 
+        * @return the data
+        */
+       public byte[] getData() {
+               return this.data;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("BGPNotificationMessage [error=");
+               builder.append(this.error);
+               builder.append(", data=");
+               builder.append(Arrays.toString(this.data));
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/message/BGPOpenMessage.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/message/BGPOpenMessage.java
new file mode 100644 (file)
index 0000000..ad475cd
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.message;
+
+import java.util.List;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * Representation of BGPOpen message.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.2">BGP Open Message</a>
+ */
+public final class BGPOpenMessage implements BGPMessage {
+
+       private static final long serialVersionUID = -3507481736478860117L;
+
+       /**
+        * Current BGP version.
+        */
+       public static final int BGP_VERSION = 4;
+
+       private final ASNumber myAS;
+
+       private final short holdTime;
+
+       private final IPv4Address bgpId;
+
+       private final List<BGPParameter> optParams;
+
+       /**
+        * Creates BGPOpen message.
+        * 
+        * @param myAS ASNumber of the BGP speaker
+        * @param holdTime proposed value of the Hold Timer
+        * @param bgpId IPv4 Address of the BGP speaker
+        * @param optParams List of optional parameters
+        */
+       public BGPOpenMessage(final ASNumber myAS, final short holdTime, final IPv4Address bgpId, final List<BGPParameter> optParams) {
+               super();
+               this.myAS = myAS;
+               this.holdTime = holdTime;
+               this.bgpId = bgpId;
+               this.optParams = optParams;
+       }
+
+       /**
+        * Returns the AS number of the BGP speaker.
+        * 
+        * @return myAS
+        */
+       public ASNumber getMyAS() {
+               return this.myAS;
+       }
+
+       /**
+        * Returns the value of the Hold timer.
+        * 
+        * @return the holdTime
+        */
+       public short getHoldTime() {
+               return this.holdTime;
+       }
+
+       /**
+        * Returns BGP identifier of the speaker (his IP address).
+        * 
+        * @return the bgpId
+        */
+       public IPv4Address getBgpId() {
+               return this.bgpId;
+       }
+
+       /**
+        * Returns optional parameters in form of TLVs.
+        * 
+        * @return the optParams
+        */
+       public List<BGPParameter> getOptParams() {
+               return this.optParams;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("BGPOpenMessage [myAS=");
+               builder.append(this.myAS);
+               builder.append(", holdTime=");
+               builder.append(this.holdTime);
+               builder.append(", bgpId=");
+               builder.append(this.bgpId);
+               builder.append(", optParams=");
+               builder.append(this.optParams);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/AS4BytesCapability.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/AS4BytesCapability.java
new file mode 100644 (file)
index 0000000..00cdc6c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.parameter;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * AS 4B Numbers capability.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc6793">BGP Support for 4-Octet AS Number Space</a>
+ */
+public final class AS4BytesCapability extends CapabilityParameter {
+
+       /**
+        * Capability code for 4B AS.
+        */
+       public static final int CODE = 65;
+
+       private final ASNumber as;
+
+       public AS4BytesCapability(final ASNumber as) {
+               super(CODE);
+               this.as = as;
+       }
+
+       /**
+        * Returns 4B AS Number.
+        * 
+        * @return 4B AS Number
+        */
+       public ASNumber getASNumber() {
+               return this.as;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("AS4BytesCapability [as=");
+               builder.append(this.as);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/CapabilityParameter.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/CapabilityParameter.java
new file mode 100644 (file)
index 0000000..4220b12
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.parameter;
+
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+
+/**
+ * Capability parameter superclass.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc3392#section-4">Capabilities Optional Parameter</a>
+ */
+public abstract class CapabilityParameter implements BGPParameter {
+
+       private final int TYPE = 2;
+
+       private final int code;
+
+       CapabilityParameter(final int code) {
+               this.code = code;
+       }
+
+       /**
+        * Returns capability code specific capability parameter.
+        * 
+        * @return capability code
+        */
+       public int getCode() {
+               return this.code;
+       }
+
+       @Override
+       public int getType() {
+               return this.TYPE;
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/GracefulCapability.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/GracefulCapability.java
new file mode 100644 (file)
index 0000000..3e20276
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.parameter;
+
+import java.util.Map;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+
+
+/**
+ * Graceful restart capability parameter as described in:
+ * 
+ * <a href="http://tools.ietf.org/html/rfc4724#section-3">Graceful Restart Capability</a>
+ */
+public final class GracefulCapability extends CapabilityParameter {
+
+       /**
+        * Capability code for GR)
+        */
+       private static final int CODE = 64;
+
+       private final boolean restartFlag;
+
+       private final int restartTimerValue;
+
+       private final Map<BGPTableType, Boolean> tableTypes;
+
+       /**
+        * Creates new Graceful restart capability.
+        * 
+        * @param restartFlag should be false
+        * @param restartTimerValue should be 0
+        * @param tableTypes supported AFI/SAFI along with Forwarding state flag (should be true)
+        */
+       public GracefulCapability(final boolean restartFlag, final int restartTimerValue, final Map<BGPTableType, Boolean> tableTypes) {
+               super(CODE);
+               this.restartFlag = restartFlag;
+               this.restartTimerValue = restartTimerValue;
+               this.tableTypes = tableTypes;
+       }
+
+       /**
+        * Was router restarted?
+        * 
+        * @return the restartFlag
+        */
+       public boolean isRestartFlag() {
+               return this.restartFlag;
+       }
+
+       /**
+        * Currently should be always 0.
+        * 
+        * @return the restartTimerValue
+        */
+       public int getRestartTimerValue() {
+               return this.restartTimerValue;
+       }
+
+       /**
+        * Return supported AFI/SAFI along with Forwarding state flag.
+        * 
+        * @return the tableTypes
+        */
+       public Map<BGPTableType, Boolean> getTableTypes() {
+               return this.tableTypes;
+       }
+}
diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/MultiprotocolCapability.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/parameter/MultiprotocolCapability.java
new file mode 100644 (file)
index 0000000..1cfdeab
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.parameter;
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+
+/**
+ * Multiprotocol capability Parameter as described in:
+ * 
+ * <a href="http://tools.ietf.org/html/rfc4760#section-8">Use of BGP Capability Advertisement/a>
+ */
+public final class MultiprotocolCapability extends CapabilityParameter {
+
+       /**
+        * Capability Code is set to 1, which indicates Multiprotocol Extensions capabilities.
+        */
+       public static final int CODE = 1;
+
+       private final BGPTableType tableType;
+
+       /**
+        * Creates Multiprotocol Capability.
+        * 
+        * 
+        * @param type bgp table type
+        */
+       public MultiprotocolCapability(final BGPTableType type) {
+               super(CODE);
+               this.tableType = type;
+       }
+
+       /**
+        * Returns numeric representation of AFI.
+        * 
+        * @return AFI
+        */
+       public BGPAddressFamily getAfi() {
+               return this.tableType.getAddressFamily();
+       }
+
+       /**
+        * Returns numeric representation of SAFI.
+        * 
+        * @return SAFI
+        */
+       public BGPSubsequentAddressFamily getSafi() {
+               return this.tableType.getSubsequentAddressFamily();
+       }
+
+       /**
+        * Returns BGP Table Type that is supported by the sender of this capability.
+        * 
+        * @return BGP Table Type
+        */
+       public BGPTableType getTableType() {
+               return this.tableType;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("MultiprotocolCapability [tableType=");
+               builder.append(this.tableType);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-api/src/site/apt/index.apt.vm b/bgp/parser-api/src/site/apt/index.apt.vm
new file mode 100644 (file)
index 0000000..240ca24
--- /dev/null
@@ -0,0 +1,6 @@
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
diff --git a/bgp/parser-api/src/site/site.xml b/bgp/parser-api/src/site/site.xml
new file mode 100644 (file)
index 0000000..e468b3b
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+  <body>
+    <head>${project.artifactId}</head>
+    <links>
+      <item name="${project.artifactId}" href="index.html"/>
+    </links>
+
+    <menu ref="parent"/>
+
+    <menu ref="reports"/>
+
+    
+  </body>
+</project>
+
diff --git a/bgp/parser-api/src/test/java/org/opendaylight/protocol/bgp/parser/APITest.java b/bgp/parser-api/src/test/java/org/opendaylight/protocol/bgp/parser/APITest.java
new file mode 100644 (file)
index 0000000..a55bb89
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.UnknownHostException;
+import java.util.Collections;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.RouteTag;
+import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPLinkState;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPNodeState;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.BGPPrefixState;
+import org.opendaylight.protocol.bgp.parser.BGPRouteState;
+import org.opendaylight.protocol.util.DefaultingTypesafeContainer;
+import com.google.common.collect.Sets;
+
+public class APITest {
+
+       BaseBGPObjectState objState = new BaseBGPObjectState(BGPOrigin.EGP, null);
+       NetworkObjectState netObjState = new NetworkObjectState(null, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+
+       @Test
+       public void testAPI() {
+               final BGPRouteState<IPv4Address> route1 = new BGPRouteState<IPv4Address>(this.objState, new NetworkRouteState<IPv4Address>(new IPv4NextHop(IPv4.FAMILY.addressForString("192.168.5.4"))));
+               final BGPRouteState<IPv4Address> route2 = new BGPRouteState<IPv4Address>(new BaseBGPObjectState(BGPOrigin.IGP, null), new NetworkRouteState<IPv4Address>(new IPv4NextHop(IPv4.FAMILY.addressForString("172.168.5.42"))));
+
+               assertEquals(route1, route1.newInstance());
+               assertNotSame(route1.hashCode(), new BGPRouteState<IPv4Address>(route2).hashCode());
+               assertEquals(route1.toString(), route1.toString());
+               assertNull(route1.getAggregator());
+               assertNotNull(route1.getObjectState().getNextHop());
+               assertEquals(route1.getOrigin(), BGPOrigin.EGP);
+
+               final BGPParsingException e = new BGPParsingException("Some error message.");
+               assertEquals("Some error message.", e.getError());
+
+               final BGPParsingException e2 = new BGPParsingException("Some error message.", new IllegalAccessException());
+               assertEquals("Some error message.", e2.getError());
+               assertTrue(e2.getCause() instanceof IllegalAccessException);
+       }
+
+       @Test
+       public void testBGPHeaderParser() {
+               final BGPMessageHeader h = new BGPMessageHeader();
+               try {
+                       h.fromBytes(new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                                       (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                                       (byte) 0, (byte) 0 });
+                       fail("Exception should have occured.");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Too few bytes in passed array. Passed: 18. Expected: >= " + BGPMessageHeader.COMMON_HEADER_LENGTH + ".",
+                                       e.getMessage());
+               }
+
+               h.fromBytes(new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0,
+                               (byte) 27, (byte) 1 });
+
+               assertEquals(h.getType(), 1);
+               assertEquals(h.getLength(), 27);
+               assertTrue(h.isParsed());
+
+               final BGPMessageHeader hh = new BGPMessageHeader(1, 27);
+
+               final byte[] expected = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0, (byte) 27, (byte) 1 };
+
+               assertArrayEquals(expected, hh.toBytes());
+
+               hh.setParsed();
+
+               assertFalse(hh.isParsed());
+       }
+
+       @Test
+       public void testPrefixes() throws UnknownHostException {
+               final NetworkPrefixState state = new NetworkPrefixState(this.netObjState, Sets.<RouteTag> newTreeSet(), null);
+
+               final BGPPrefixState ipv4 = new BGPPrefixState(this.objState, state);
+               final BGPPrefixState ipv6 = new BGPPrefixState(new BaseBGPObjectState(BGPOrigin.EGP, null), state);
+
+               assertEquals(ipv4.toString(), ipv4.newInstance().toString());
+               assertNotSame(ipv4, new BGPPrefixState(ipv6));
+       }
+
+       @Test
+       public void testNodeState() {
+               final BGPNodeState n1 = new BGPNodeState(this.objState, new NetworkNodeState(this.netObjState, Collections.<TopologyIdentifier, TopologyNodeInformation> emptyMap(), Collections.<ISISAreaIdentifier> emptySet(), false, false, Collections.<RouterIdentifier> emptySet(), ""));
+               assertEquals(n1, n1.newInstance());
+               assertEquals(n1, new BGPNodeState(n1));
+       }
+
+       @Test
+       public void testLinkState() {
+               final DefaultingTypesafeContainer<Metric<?>> m = new DefaultingTypesafeContainer<Metric<?>>();
+               m.setDefaultEntry(new TEMetric(15L));
+               final BGPLinkState l1 = new BGPLinkState(this.objState, new NetworkLinkState(this.netObjState, m, null, null, null, LinkProtectionType.UNPROTECTED, null, null, null, null));
+               assertEquals(l1, l1.newInstance());
+               assertEquals(l1, new BGPLinkState(l1));
+       }
+}
diff --git a/bgp/parser-impl/.gitignore b/bgp/parser-impl/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/bgp/parser-impl/.project b/bgp/parser-impl/.project
new file mode 100644 (file)
index 0000000..9814b40
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>bgp-updated-parser-impl</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bgp/parser-impl/pom.xml b/bgp/parser-impl/pom.xml
new file mode 100644 (file)
index 0000000..87be8a5
--- /dev/null
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>bgp-parent</artifactId>
+               <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-parser-impl</artifactId>
+       <description>BGP Parser Implementation Updated to draft-02</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-linkstate</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>util</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-parser-api</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-util</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <version>${junit.version}</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>mockito-configuration</artifactId>
+                       <version>1.0</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.guava</groupId>
+                       <artifactId>guava</artifactId>
+                       <version>${guava.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.code.findbugs</groupId>
+                       <artifactId>jsr305</artifactId>
+                       <version>2.0.1</version>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Private-Package>
+                                                       javax.annotation.*,
+                                                       org.opendaylight.protocol.bgp.parser.impl.*
+                                               </Private-Package>
+                                               <Import-Package>
+                                                       org.opendaylight.protocol.bgp.parser.message,
+                                                       org.opendaylight.protocol.bgp.parser.parameter,
+                                                       org.opendaylight.protocol.bgp.concepts,
+                                                       org.opendaylight.protocol.bgp.linkstate,
+                            org.opendaylight.protocol.bgp.parser,
+                            org.opendaylight.protocol.bgp.util,
+                                                       org.opendaylight.protocol.concepts,
+                                                       org.opendaylight.protocol.framework,
+                            org.opendaylight.protocol.util,
+                                                       com.google.common.*,
+                                                       org.slf4j,
+                                                       org.apache.commons.lang
+                                               </Import-Package>
+                                               <Export-Package>
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-jar-plugin</artifactId>
+                               <version>2.4</version>
+                               <executions>
+                                       <execution>
+                                               <phase>package</phase>
+                                               <goals>
+                                                       <goal>test-jar</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>BGP-PARSER-IMPL Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/AbstractLinkstateMP.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/AbstractLinkstateMP.java
new file mode 100644 (file)
index 0000000..02f17f6
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+
+/**
+ *
+ */
+public abstract class AbstractLinkstateMP<T> implements MPReach<T> {
+
+       private final boolean reachable;
+
+       private final long identifier;
+
+       private final SourceProtocol sourceProtocol;
+
+       protected AbstractLinkstateMP(final long identifier, final SourceProtocol sourceProtocol, final boolean reachable) {
+               this.identifier = identifier;
+               this.sourceProtocol = sourceProtocol;
+               this.reachable = reachable;
+       }
+
+       @Override
+       public boolean isReachable() {
+               return this.reachable;
+       }
+
+       public long getIdentifier() {
+               return this.identifier;
+       }
+
+       public SourceProtocol getSourceProtocol() {
+               return this.sourceProtocol;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (int) (this.identifier ^ (this.identifier >>> 32));
+               result = prime * result + (this.reachable ? 1231 : 1237);
+               result = prime * result + ((this.sourceProtocol == null) ? 0 : this.sourceProtocol.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final AbstractLinkstateMP<?> other = (AbstractLinkstateMP<?>) obj;
+               if (this.identifier != other.identifier)
+                       return false;
+               if (this.reachable != other.reachable)
+                       return false;
+               if (this.sourceProtocol != other.sourceProtocol)
+                       return false;
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("AbstractLinkstateMP [reachable=");
+               builder.append(this.reachable);
+               builder.append(", identifier=");
+               builder.append(this.identifier);
+               builder.append(", sourceProtocol=");
+               builder.append(this.sourceProtocol);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPAggregatorImpl.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPAggregatorImpl.java
new file mode 100644 (file)
index 0000000..6b7ed1a
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import org.opendaylight.protocol.bgp.concepts.BGPAggregator;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * Implementation of BGP Aggregator object.
+ * @param <T> subtype of Network Address
+ */
+public class BGPAggregatorImpl<T extends NetworkAddress<T>> implements
+               BGPAggregator {
+
+       private final ASNumber asNumber;
+
+       private final T address;
+
+       public BGPAggregatorImpl(ASNumber asNumber, T address) {
+               this.address = address;
+               this.asNumber = asNumber;
+       }
+
+       @Override
+       public ASNumber getASNumber() {
+               return this.asNumber;
+       }
+
+       @Override
+       public T getNetworkAddress() {
+               return this.address;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.address == null) ? 0 : this.address.hashCode());
+               result = prime * result
+                               + ((this.asNumber == null) ? 0 : this.asNumber.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final BGPAggregatorImpl<?> other = (BGPAggregatorImpl<?>) obj;
+               if (this.address == null) {
+                       if (other.address != null)
+                               return false;
+               } else if (!this.address.equals(other.address))
+                       return false;
+               if (this.asNumber == null) {
+                       if (other.asNumber != null)
+                               return false;
+               } else if (!this.asNumber.equals(other.asNumber))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("BGPAggregatorImpl [asNumber=");
+               builder.append(this.asNumber);
+               builder.append(", address=");
+               builder.append(this.address);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPIPv4PrefixMP.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPIPv4PrefixMP.java
new file mode 100644 (file)
index 0000000..f53cc7c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
+
+/**
+ * IPv4 implementation of {@link MPReach}.
+ */
+public class BGPIPv4PrefixMP extends AbstractLinkstateMP<IPv4PrefixIdentifier> {
+
+       private final Set<IPv4PrefixIdentifier> prefixes;
+
+       /**
+        * Creates BGP IPv4 Prefix.
+        * 
+        * @param identifier long
+        * @param sourceProtocol {@link SourceProtocol}
+        * @param prefixes set of prefixes
+        * @param reachable true if the attribute is MPReach, false if the attribute is MPUnreach
+        */
+       public BGPIPv4PrefixMP(final long identifier, final SourceProtocol sourceProtocol, final Set<IPv4PrefixIdentifier> prefixes,
+                       final boolean reachable) {
+               super(identifier, sourceProtocol, reachable);
+               this.prefixes = prefixes;
+       }
+
+       @Override
+       public Set<IPv4PrefixIdentifier> getNlri() {
+               return this.prefixes;
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPIPv6PrefixMP.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPIPv6PrefixMP.java
new file mode 100644 (file)
index 0000000..65ac1fa
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+import org.opendaylight.protocol.bgp.linkstate.IPv6PrefixIdentifier;
+
+/**
+ * IPv6 implementation of {@link MPReach}.
+ */
+public class BGPIPv6PrefixMP extends AbstractLinkstateMP<IPv6PrefixIdentifier> {
+
+       private final Set<IPv6PrefixIdentifier> prefixes;
+
+       /**
+        * Creates BGP IPv6 Prefix.
+        * 
+        * @param identifier long
+        * @param sourceProtocol {@link SourceProtocol}
+        * @param prefixes set of prefix descriptors
+        * @param reachable true if the attribute is MPReach, false if the attribute is MPUnreach
+        */
+       public BGPIPv6PrefixMP(final long identifier, final SourceProtocol sourceProtocol, final Set<IPv6PrefixIdentifier> prefixes,
+                       final boolean reachable) {
+               super(identifier, sourceProtocol, reachable);
+               this.prefixes = prefixes;
+       }
+
+       @Override
+       public Set<IPv6PrefixIdentifier> getNlri() {
+               return this.prefixes;
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPLinkMP.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPLinkMP.java
new file mode 100644 (file)
index 0000000..dc49b86
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+
+/**
+ * 
+ * Link State MP_(UN)REACH_NLRI (contains BGP Link inf.)
+ * 
+ */
+public class BGPLinkMP extends AbstractLinkstateMP<LinkIdentifier> {
+
+       private final Set<LinkIdentifier> link;
+
+       /**
+        * Creates BGP LINK MP Reach.
+        * 
+        * @param identifier long
+        * @param sourceProtocol {@link SourceProtocol}
+        * @param prefixes set of prefix descriptors
+        * @param reachable true if the attribute is MPReach, false if the attribute is MPUnreach
+        */
+       public BGPLinkMP(final long identifier, final SourceProtocol sourceProtocol, final boolean reachable, final Set<LinkIdentifier> link) {
+               super(identifier, sourceProtocol, reachable);
+               this.link = link;
+       }
+
+       @Override
+       public Set<LinkIdentifier> getNlri() {
+               return this.link;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.link == null) ? 0 : this.link.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final BGPLinkMP other = (BGPLinkMP) obj;
+               if (this.link == null) {
+                       if (other.link != null)
+                               return false;
+               } else if (!this.link.equals(other.link))
+                       return false;
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("BGPLinkMP [link=");
+               builder.append(this.link);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPMessageFactory.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPMessageFactory.java
new file mode 100644 (file)
index 0000000..1ad19c7
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPNotificationMessageParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPOpenMessageParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ *
+ */
+public class BGPMessageFactory implements BGPMessageParser {
+
+       private final static Logger logger = LoggerFactory.getLogger(BGPMessageFactory.class);
+
+       public BGPMessageFactory() {
+       }
+
+       @Override
+       public BGPMessage parse(final byte[] bytes, final ProtocolMessageHeader msgH) throws DeserializerException, DocumentedException {
+               final BGPMessageHeader msgHeader = (BGPMessageHeader) msgH;
+               if (bytes == null)
+                       throw new IllegalArgumentException("Array of bytes is mandatory.");
+               if (msgHeader == null)
+                       throw new IllegalArgumentException("BGPMessageHeader is mandatory.");
+               if (msgHeader.getLength() < BGPMessageHeader.COMMON_HEADER_LENGTH)
+                       throw new BGPDocumentedException("Message length field not within valid range.", BGPError.BAD_MSG_LENGTH, ByteArray.intToBytes(msgHeader.getLength()));
+               if (bytes.length != (msgHeader.getLength() - BGPMessageHeader.COMMON_HEADER_LENGTH))
+                       throw new BGPParsingException("Size doesn't match size specified in header. Passed: " + bytes.length + "; Expected: "
+                                       + (msgHeader.getLength() - BGPMessageHeader.COMMON_HEADER_LENGTH) + ". " + msgHeader.getLength());
+
+               logger.debug("Attempt to parse message from bytes: {}", ByteArray.bytesToHexString(bytes));
+
+               BGPMessage msg = null;
+
+               switch (msgHeader.getType()) {
+               case 1:
+                       msg = BGPOpenMessageParser.parse(bytes);
+                       logger.debug("Received and parsed Open Message: {}", msg);
+                       break;
+               case 2:
+                       msg = BGPUpdateMessageParser.parse(bytes, msgHeader.getLength());
+                       logger.debug("Received and parsed Update Message: {}", msg);
+                       break;
+               case 3:
+                       msg = BGPNotificationMessageParser.parse(bytes);
+                       logger.debug("Received and parsed Notification Message: {}", msg);
+                       break;
+               case 4:
+                       msg = new BGPKeepAliveMessage();
+                       if (msgHeader.getLength() != BGPMessageHeader.COMMON_HEADER_LENGTH)
+                               throw new BGPDocumentedException("Message length field not within valid range.", BGPError.BAD_MSG_LENGTH, ByteArray.intToBytes(msgHeader.getLength()));
+                       break;
+               default:
+                       throw new BGPDocumentedException("Unhandled message type " + msgHeader.getType(), BGPError.BAD_MSG_TYPE, ByteArray.intToBytes(msgHeader.getType()));
+               }
+               return msg;
+       }
+
+       @Override
+       public byte[] put(final ProtocolMessage msg) {
+               final BGPMessage bgpMsg = (BGPMessage) msg;
+               if (bgpMsg == null)
+                       throw new IllegalArgumentException("BGPMessage is mandatory.");
+
+               logger.trace("Serializing {}", bgpMsg);
+
+               byte[] msgBody = null;
+               int msgType = 0;
+
+               /*
+                * Update message is not supported
+                */
+               if (bgpMsg instanceof BGPOpenMessage) {
+                       msgType = 1;
+                       msgBody = BGPOpenMessageParser.put((BGPOpenMessage) bgpMsg);
+               } else if (bgpMsg instanceof BGPNotificationMessage) {
+                       msgType = 3;
+                       msgBody = BGPNotificationMessageParser.put((BGPNotificationMessage) bgpMsg);
+               } else if (bgpMsg instanceof BGPKeepAliveMessage) {
+                       msgType = 4;
+                       msgBody = new byte[0];
+               } else {
+                       throw new IllegalArgumentException("Unknown instance of BGPMessage. Passed " + bgpMsg.getClass());
+               }
+
+               final BGPMessageHeader msgHeader = new BGPMessageHeader(msgType, msgBody.length + BGPMessageHeader.COMMON_HEADER_LENGTH);
+
+               final byte[] headerBytes = msgHeader.toBytes();
+               final byte[] retBytes = new byte[headerBytes.length + msgBody.length];
+
+               ByteArray.copyWhole(headerBytes, retBytes, 0);
+               ByteArray.copyWhole(msgBody, retBytes, BGPMessageHeader.COMMON_HEADER_LENGTH);
+
+               logger.trace("Serialized BGP message {}.", Arrays.toString(retBytes));
+               return retBytes;
+       }
+
+       @Override
+       public void close() throws IOException {
+               // nothing to close
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPNodeMP.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPNodeMP.java
new file mode 100644 (file)
index 0000000..83e14b9
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+
+/**
+ * 
+ * Link State MP_(UN)REACH_NLRI (contains BGP Node inf.)
+ * 
+ */
+public class BGPNodeMP extends AbstractLinkstateMP<NodeIdentifier> {
+
+       private final Set<NodeIdentifier> nodes;
+
+       /**
+        * Creates BGP Node MP Reach.
+        * 
+        * @param identifier long
+        * @param sourceProtocol {@link SourceProtocol}
+        * @param prefixes set of prefix descriptors
+        * @param reachable true if the attribute is MPReach, false if the attribute is MPUnreach
+        */
+       public BGPNodeMP(final long identifier, final SourceProtocol sourceProtocol, final boolean reachable, final Set<NodeIdentifier> nodes) {
+               super(identifier, sourceProtocol, reachable);
+               this.nodes = nodes;
+       }
+
+       @Override
+       public Set<NodeIdentifier> getNlri() {
+               return this.nodes;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.nodes == null) ? 0 : this.nodes.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final BGPNodeMP other = (BGPNodeMP) obj;
+               if (this.nodes == null) {
+                       if (other.nodes != null)
+                               return false;
+               } else if (!this.nodes.equals(other.nodes))
+                       return false;
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("BGPNodeMP [nodes=");
+               builder.append(this.nodes);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateEventBuilder.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateEventBuilder.java
new file mode 100644 (file)
index 0000000..1fe1ba2
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.BGPAggregator;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateEvent;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.LinkStateParser;
+import org.opendaylight.protocol.bgp.util.BGPIPv4PrefixImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6PrefixImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPLinkImpl;
+import org.opendaylight.protocol.bgp.util.BGPNodeImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv6PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkImpl;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeImpl;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+/**
+ * 
+ * Builds BGPUpdateEvent. This code was originally in {@link BGPUpdateMessageParser}. Moved here during refactoring.
+ * 
+ * Withdrawn routes or nlri that contain directly prefixes, can contain only IPv4 Prefixes.
+ */
+@NotThreadSafe
+public class BGPUpdateEventBuilder {
+
+       private static final Logger log = LoggerFactory.getLogger(BGPUpdateEventBuilder.class);
+
+       /**
+        * 
+        * Length of the withdrawn_routes field, in bytes.
+        */
+
+       private int withdrawnRoutesLength;
+
+       /**
+        * 
+        * List of IP address prefixes for the routes that are being withdrawn. Can be empty when there are no routes to
+        * 
+        * withdraw.
+        */
+
+       private Set<Prefix<IPv4Address>> withdrawnRoutes;
+
+       /**
+        * 
+        * Length of the total_path_attributes field, in bytes.
+        */
+
+       private int totalPathAttrLength;
+
+       /**
+        * 
+        * List of path attributes. Can be empty when there are only withdrawn routes present.
+        */
+
+       private List<PathAttribute> pathAttributes;
+
+       /**
+        * 
+        * List of IP address prefixes of routes that are advertised.
+        */
+
+       private Set<Prefix<IPv4Address>> nlri;
+
+       /**
+        * 
+        * Fills in BGP Objects that need to be added to topology. The method first checks and sets Path Attributes. If the
+        * 
+        * NLRI field is not empty, create for each of the prefixes present in NLRI, a BGPRoute with the attributes and
+        * 
+        * corresponding Prefix. If MP_REACH_NLRI attribute is found, check its NLRI, if its not of type Link State, do the
+        * 
+        * same.
+        * 
+        * 
+        * 
+        * @param pathAttributes
+        * 
+        * @param nlri
+        * 
+        * 
+        * 
+        * @return set of BGP Objects that need to be added
+        * 
+        * @throws BGPParsingException
+        */
+
+       private Set<BGPObject> fillAddedObjects(final List<PathAttribute> pathAttributes, final Set<Prefix<IPv4Address>> nlri)
+                       throws BGPParsingException {
+               BGPOrigin origin = null;
+               ASPath aspath = null;
+               IPv4NextHop nextHop = null;
+               BGPAggregator aggregator = null;
+               final Set<ExtendedCommunity> ecomm = Sets.newHashSet();
+               final Set<Community> comm = Sets.newHashSet();
+               final Map<Integer, ByteList> linkstate = Maps.newHashMap();
+               for (final PathAttribute pa : pathAttributes) {
+                       if (pa.getValue() instanceof BGPOrigin) {
+                               origin = (BGPOrigin) pa.getValue();
+                       } else if (pa.getValue() instanceof ASPath) {
+                               aspath = (ASPath) pa.getValue();
+                       } else if (pa.getValue() instanceof IPv4NextHop) {
+                               nextHop = (IPv4NextHop) pa.getValue();
+                       } else if (pa.getValue() instanceof BGPAggregator) {
+                               aggregator = (BGPAggregator) pa.getValue();
+                       } else if (pa.getValue() instanceof Set) {
+                               for (final Object o : (Set<?>) pa.getValue()) {
+                                       if (o instanceof ExtendedCommunity) {
+                                               ecomm.add((ExtendedCommunity) o);
+                                       } else if (o instanceof Community) {
+                                               comm.add((Community) o);
+                                       }
+                               }
+                       } else if (pa.getValue() instanceof Map) {
+                               for (final Entry<?, ?> entry : ((Map<?, ?>) pa.getValue()).entrySet()) {
+                                       if (entry.getValue() instanceof ByteList) {
+                                               final ByteList lb = (ByteList) entry.getValue();
+                                               linkstate.put((Integer) entry.getKey(), lb);
+                                       }
+                               }
+                       }
+               }
+
+               final BaseBGPObjectState base = new BaseBGPObjectState(origin, aggregator);
+               final NetworkObjectState nos = new NetworkObjectState(aspath, comm, ecomm);
+               final Set<BGPObject> added = new HashSet<BGPObject>();
+               if (!nlri.isEmpty()) {
+                       final NetworkRouteState<IPv4Address> nrs = new NetworkRouteState<>(nos, nextHop);
+                       for (final Prefix<IPv4Address> p : nlri) {
+                               added.add(new BGPIPv4RouteImpl(p, base, nrs));
+                       }
+               }
+
+               final MPReach<?> mpreach = findMP(pathAttributes, true);
+               if (mpreach != null) {
+                       if (mpreach instanceof IPv4MP) {
+                               final IPv4MP ipv4mp = (IPv4MP) mpreach;
+                               final IPv4NextHop v4nextHop = ipv4mp.getNextHop();
+                               final NetworkRouteState<IPv4Address> nrs = new NetworkRouteState<>(nos, v4nextHop);
+                               for (final Prefix<IPv4Address> p : ipv4mp.getNlri()) {
+                                       added.add(new BGPIPv4RouteImpl(p, base, nrs));
+                               }
+                       } else if (mpreach instanceof IPv6MP) {
+                               final IPv6MP ipv6mp = (IPv6MP) mpreach;
+                               final IPv6NextHop v6nextHop = ipv6mp.getNextHop();
+                               final NetworkRouteState<IPv6Address> nrs = new NetworkRouteState<>(nos, v6nextHop);
+                               for (final Prefix<IPv6Address> p : ipv6mp.getNlri()) {
+                                       added.add(new BGPIPv6RouteImpl(p, base, nrs));
+                               }
+                       } else if (mpreach instanceof BGPNodeMP) {
+                               final Set<NodeIdentifier> nodes = ((BGPNodeMP) mpreach).getNlri();
+                               if (!LinkStateParser.verifyNode(linkstate.keySet()))
+                                       throw new BGPParsingException("Some attributes from LINK_STATE Path attribute don't belong to advertised node.");
+                               for (final NodeIdentifier desc : nodes) {
+                                       final NetworkNodeImpl n = LinkStateParser.parseNodeAttributes(desc, linkstate);
+                                       n.setASPath(aspath);
+                                       n.setExtendedCommunities(ecomm);
+                                       n.setCommunities(comm);
+                                       final BGPNodeImpl bgpNode = new BGPNodeImpl(base, desc, n.currentState());
+                                       log.debug("Adding bgp node {}", bgpNode);
+                                       added.add(bgpNode);
+                               }
+                       } else if (mpreach instanceof BGPLinkMP) {
+                               final Set<LinkIdentifier> links = ((BGPLinkMP) mpreach).getNlri();
+                               if (!LinkStateParser.verifyLink(linkstate.keySet()))
+                                       throw new BGPParsingException("Some attributes from LINK_STATE Path attribute don't belong to advertised link.");
+                               for (final LinkIdentifier desc : links) {
+                                       final NetworkLinkImpl l = LinkStateParser.parseLinkAttributes(desc, linkstate);
+                                       l.setASPath(aspath);
+                                       l.setExtendedCommunities(ecomm);
+                                       l.setCommunities(comm);
+                                       log.debug("Adding bgp link {}", l);
+                                       added.add(new BGPLinkImpl(base, desc, l.currentState()));
+                               }
+                       } else if (mpreach instanceof BGPIPv4PrefixMP) {
+                               final Set<IPv4PrefixIdentifier> prefixes = ((BGPIPv4PrefixMP) mpreach).getNlri();
+                               if (!LinkStateParser.verifyPrefix(linkstate.keySet()))
+                                       throw new BGPParsingException("Some attributes from LINK_STATE Path attribute don't belong to advertised prefix.");
+                               final NetworkPrefixState nps = LinkStateParser.parsePrefixAttributes(((BGPIPv4PrefixMP) mpreach).getSourceProtocol(), nos,
+                                               linkstate);
+                               for (final IPv4PrefixIdentifier desc : prefixes) {
+                                       log.debug("Adding IPv4 Prefix {} State {}", desc, nps);
+                                       added.add(new BGPIPv4PrefixImpl(base, desc, nps));
+                               }
+                       } else if (mpreach instanceof BGPIPv6PrefixMP) {
+                               final Set<IPv6PrefixIdentifier> prefixes = ((BGPIPv6PrefixMP) mpreach).getNlri();
+                               if (!LinkStateParser.verifyPrefix(linkstate.keySet()))
+                                       throw new BGPParsingException("Some attributes from LINK_STATE Path attribute don't belong to advertised prefix.");
+
+                               final NetworkPrefixState nps = LinkStateParser.parsePrefixAttributes(((BGPIPv6PrefixMP) mpreach).getSourceProtocol(), nos,
+                                               linkstate);
+                               for (final IPv6PrefixIdentifier desc : prefixes) {
+                                       log.debug("Adding IPv6 Prefix {} State {}", desc, nps);
+                                       added.add(new BGPIPv6PrefixImpl(base, desc, nps));
+                               }
+                       }
+               }
+               return added;
+
+       }
+
+       /**
+        * Fills in Identifiers that need to be removed. First, check field withdrawn routes, that can contain only IPv4
+        * prefixes. Then, check the presence of MP_UNREACH_NLRI and if its NLRI contains Prefixes, add them to removed
+        * field. For link state information, Node & LinkIdentifiers are added to the Set.
+        * 
+        * @param pathAttributes
+        * @param withdrawnRoutes
+        * 
+        * @return set of identifiers that need to be removed
+        */
+
+       private Set<?> fillRemovedObjects(final List<PathAttribute> pathAttributes, final Set<Prefix<IPv4Address>> withdrawnRoutes) {
+               final Set<Object> removed = Sets.newHashSet();
+               if (!withdrawnRoutes.isEmpty()) {
+                       removed.addAll(withdrawnRoutes);
+               }
+               final MPReach<?> mpunreach = findMP(pathAttributes, false);
+               if (mpunreach != null) {
+                       if (mpunreach instanceof IPv4MP) {
+                               final IPv4MP ipv4mp = (IPv4MP) mpunreach;
+                               if (!ipv4mp.getNlri().isEmpty()) {
+                                       removed.addAll(ipv4mp.getNlri());
+                               }
+                       } else if (mpunreach instanceof IPv6MP) {
+                               final IPv6MP ipv6mp = (IPv6MP) mpunreach;
+                               if (!ipv6mp.getNlri().isEmpty()) {
+                                       removed.addAll(ipv6mp.getNlri());
+                               }
+                       } else if (mpunreach instanceof BGPNodeMP) {
+                               for (final NodeIdentifier node : ((BGPNodeMP) mpunreach).getNlri()) {
+                                       removed.add(node);
+                               }
+                       } else if (mpunreach instanceof BGPLinkMP) {
+                               for (final LinkIdentifier link : ((BGPLinkMP) mpunreach).getNlri()) {
+                                       removed.add(link);
+                               }
+                       } else if (mpunreach instanceof BGPIPv4PrefixMP) {
+                               for (final IPv4PrefixIdentifier pref : ((BGPIPv4PrefixMP) mpunreach).getNlri()) {
+                                       removed.add(pref);
+                               }
+                       } else if (mpunreach instanceof BGPIPv6PrefixMP) {
+                               for (final IPv6PrefixIdentifier pref : ((BGPIPv6PrefixMP) mpunreach).getNlri()) {
+                                       removed.add(pref);
+                               }
+                       }
+               }
+               return removed;
+
+       }
+
+       /**
+        * Finds MPReach object in Path Attribute list (depending on reachability boolean) and returns typecasted object.
+        * 
+        * @param arrayList list of path attributes
+        * @param reachable true if we search for MP_REACH_NLRI, false if we search for MP_UNREACH_NLRI
+        * 
+        * @return cated MPReach object
+        */
+       private static <T> MPReach<?> findMP(final Collection<PathAttribute> arrayList, final boolean reachable) {
+               for (final PathAttribute o : arrayList) {
+                       final Object v = o.getValue();
+                       if (v != null && v instanceof MPReach<?>) {
+                               final MPReach<?> t = (MPReach<?>) v;
+                               if (t.isReachable() == reachable)
+                                       return t;
+                       }
+               }
+               return null;
+       }
+
+       int getWithdrawnRoutesLength() {
+               return this.withdrawnRoutesLength;
+       }
+
+       public void setWithdrawnRoutesLength(final int withdrawnRoutesLength) {
+               this.withdrawnRoutesLength = withdrawnRoutesLength;
+       }
+
+       Set<Prefix<IPv4Address>> getWithdrawnRoutes() {
+               return this.withdrawnRoutes;
+       }
+
+       public void setWithdrawnRoutes(final Set<Prefix<IPv4Address>> withdrawnRoutes) {
+               this.withdrawnRoutes = withdrawnRoutes;
+       }
+
+       int getTotalPathAttrLength() {
+               return this.totalPathAttrLength;
+       }
+
+       public void setTotalPathAttrLength(final int totalPathAttrLength) {
+               this.totalPathAttrLength = totalPathAttrLength;
+       }
+
+       List<PathAttribute> getPathAttributes() {
+               return this.pathAttributes;
+       }
+
+       public void setPathAttributes(final List<PathAttribute> pathAttributes) {
+               this.pathAttributes = pathAttributes;
+       }
+
+       Set<Prefix<IPv4Address>> getNlri() {
+               return this.nlri;
+       }
+
+       public void setNlri(final Set<Prefix<IPv4Address>> nlri) {
+               this.nlri = nlri;
+       }
+
+       /**
+        * Builds BGP Update message.
+        * 
+        * @return BGP Update message
+        * @throws BGPParsingException
+        */
+       public BGPUpdateEvent buildEvent() throws BGPParsingException {
+               final Set<BGPObject> added = fillAddedObjects(this.pathAttributes, this.nlri);
+               final Set<?> removed = fillRemovedObjects(this.pathAttributes, this.withdrawnRoutes);
+               return new BGPUpdateMessageImpl(added, removed);
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateMessageImpl.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateMessageImpl.java
new file mode 100644 (file)
index 0000000..07b4955
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+
+
+/**
+ * BGP Update Message.
+ * 
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.3">BGP-4 Update Message Format</a>
+ * 
+ */
+public class BGPUpdateMessageImpl implements BGPUpdateMessage {
+
+       private static final long serialVersionUID = -1336770400381759349L;
+
+       private final Set<BGPObject> addedObjects;
+
+       private final Set<?> removedObjects;
+
+       public BGPUpdateMessageImpl(final Set<BGPObject> addedObjects, final Set<?> removedObjects) {
+               super();
+               this.addedObjects = addedObjects;
+               this.removedObjects = removedObjects;
+       }
+
+       @Override
+       public Set<BGPObject> getAddedObjects() {
+               return this.addedObjects;
+       }
+
+       @Override
+       public Set<?> getRemovedObjects() {
+               return this.removedObjects;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.addedObjects == null) ? 0 : this.addedObjects.hashCode());
+               result = prime * result + ((this.removedObjects == null) ? 0 : this.removedObjects.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final BGPUpdateMessageImpl other = (BGPUpdateMessageImpl) obj;
+               if (this.addedObjects == null) {
+                       if (other.addedObjects != null)
+                               return false;
+               } else if (!this.addedObjects.equals(other.addedObjects))
+                       return false;
+               if (this.removedObjects == null) {
+                       if (other.removedObjects != null)
+                               return false;
+               } else if (!this.removedObjects.equals(other.removedObjects))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("BGPUpdateMessageImpl [addedObjects=");
+               builder.append(this.addedObjects);
+               builder.append(", removedObjects=");
+               builder.append(this.removedObjects);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/ByteList.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/ByteList.java
new file mode 100644 (file)
index 0000000..68af0f1
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * DTO class to avoid class cast warnings.
+ */
+public class ByteList {
+
+       private final List<byte[]> bytes;
+
+       /**
+        * Creates an empty list of byte arrays.
+        */
+       public ByteList() {
+               this.bytes = new ArrayList<byte[]>();
+       }
+
+       /**
+        * Returns underlying list of byte arrays
+        * @return underlying list of byte arrays
+        */
+       public List<byte[]> getBytes() {
+               return this.bytes;
+       }
+
+       /**
+        * Adds byte array to underlying list
+        * @param value byte array
+        */
+       public void add(byte[] value) {
+               this.bytes.add(value);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.bytes == null) ? 0 : this.bytes.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof ByteList))
+                       return false;
+               final ByteList other = (ByteList) obj;
+               if (this.bytes == null) {
+                       if (other.bytes != null)
+                               return false;
+               } else if (this.bytes.size() != other.bytes.size())
+                       return false;
+               else {
+                       for (int i = 0; i < this.bytes.size(); i ++) {
+                               if (!Arrays.equals(this.bytes.get(i), other.bytes.get(i))) {
+                                       return false;
+                               }
+                       }
+               }
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("ByteList [bytes=");
+               for (final byte[] b : this.bytes) {
+                       builder.append(Arrays.toString(b));
+               }
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/IPv4MP.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/IPv4MP.java
new file mode 100644 (file)
index 0000000..b5b6c81
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ *
+ * MP_(UN)REACH_NLRI (basic, IPv4)
+ *
+ */
+public class IPv4MP implements MPReach<Prefix<IPv4Address>> {
+
+       private final boolean reachable;
+
+       private final IPv4NextHop nextHop;
+
+       private final Set<Prefix<IPv4Address>> nlri;
+
+       public IPv4MP(final boolean reachable, final IPv4NextHop nextHop, final Set<Prefix<IPv4Address>> nlri) {
+               this.reachable = reachable;
+               this.nextHop = nextHop;
+               this.nlri = nlri;
+       }
+
+       @Override
+       public boolean isReachable() {
+               return this.reachable;
+       }
+
+       @Override
+       public Set<Prefix<IPv4Address>> getNlri() {
+               return this.nlri;
+       }
+
+       public IPv4NextHop getNextHop() {
+               return this.nextHop;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.nextHop == null) ? 0 : this.nextHop.hashCode());
+               result = prime * result + ((this.nlri == null) ? 0 : this.nlri.hashCode());
+               result = prime * result + (this.reachable ? 1231 : 1237);
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof IPv4MP))
+                       return false;
+               final IPv4MP other = (IPv4MP) obj;
+               if (this.nextHop == null) {
+                       if (other.nextHop != null)
+                               return false;
+               } else if (!this.nextHop.equals(other.nextHop))
+                       return false;
+               if (this.nlri == null) {
+                       if (other.nlri != null)
+                               return false;
+               } else if (!this.nlri.equals(other.nlri))
+                       return false;
+               if (this.reachable != other.reachable)
+                       return false;
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("IPv4MP [reachable=");
+               builder.append(this.reachable);
+               builder.append(", nextHop=");
+               builder.append(this.nextHop);
+               builder.append(", nlri=");
+               builder.append(this.nlri);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/IPv6MP.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/IPv6MP.java
new file mode 100644 (file)
index 0000000..d6a763a
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ *
+ * MP_(UN)REACH_NLRI (basic, for IPv6)
+ *
+ */
+public class IPv6MP implements MPReach<Prefix<IPv6Address>> {
+
+       private final boolean reachable;
+
+       private final IPv6NextHop nextHop;
+
+       private final Set<Prefix<IPv6Address>> nlri;
+
+       public IPv6MP(final boolean reachable, final IPv6NextHop nextHop, final Set<Prefix<IPv6Address>> nlri) {
+               this.reachable = reachable;
+               this.nextHop = nextHop;
+               this.nlri = nlri;
+       }
+
+       @Override
+       public boolean isReachable() {
+               return this.reachable;
+       }
+
+       @Override
+       public Set<Prefix<IPv6Address>> getNlri() {
+               return this.nlri;
+       }
+
+       public IPv6NextHop getNextHop() {
+               return this.nextHop;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.nextHop == null) ? 0 : this.nextHop.hashCode());
+               result = prime * result + ((this.nlri == null) ? 0 : this.nlri.hashCode());
+               result = prime * result + (this.reachable ? 1231 : 1237);
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof IPv6MP))
+                       return false;
+               final IPv6MP other = (IPv6MP) obj;
+               if (this.nextHop == null) {
+                       if (other.nextHop != null)
+                               return false;
+               } else if (!this.nextHop.equals(other.nextHop))
+                       return false;
+               if (this.nlri == null) {
+                       if (other.nlri != null)
+                               return false;
+               } else if (!this.nlri.equals(other.nlri))
+                       return false;
+               if (this.reachable != other.reachable)
+                       return false;
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("IPv6MP [reachable=");
+               builder.append(this.reachable);
+               builder.append(", nextHop=");
+               builder.append(this.nextHop);
+               builder.append(", nlri=");
+               builder.append(this.nlri);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/IdentifierTlv.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/IdentifierTlv.java
new file mode 100644 (file)
index 0000000..a71ec75
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import org.opendaylight.protocol.bgp.linkstate.AreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.DomainIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFRouteType;
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+
+/**
+ * DTO for the subTlvs from Identifier TLV.
+ *
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-idr-ls-distribution-02#section-3.2.1">Identifier TLV</a>
+ */
+public class IdentifierTlv {
+
+       private final SourceProtocol sourceProtocol;
+
+       private final DomainIdentifier domainId;
+
+       private final AreaIdentifier areaId;
+
+       private final OSPFRouteType routeType;
+
+       private final TopologyIdentifier topologyId;
+
+       private final TopologyNodeInformation topologyNodeInfo;
+
+       public IdentifierTlv(final SourceProtocol sourceProtocol,
+                       final DomainIdentifier domainId, final AreaIdentifier areaId,
+                       final OSPFRouteType routeType, final TopologyIdentifier topologyId,
+                       final TopologyNodeInformation topologyNodeInfo) {
+               this.sourceProtocol = sourceProtocol;
+               this.domainId = domainId;
+               this.areaId = areaId;
+               this.routeType = routeType;
+               this.topologyId = topologyId;
+               this.topologyNodeInfo = topologyNodeInfo;
+       }
+
+       /**
+        * @return the sourceProtocolId
+        */
+       public final SourceProtocol getSourceProtocol() {
+               return this.sourceProtocol;
+       }
+
+       /**
+        * @return the domainId
+        */
+       public final DomainIdentifier getDomainId() {
+               return this.domainId;
+       }
+
+       /**
+        * @return the areaId
+        */
+       public final AreaIdentifier getAreaId() {
+               return this.areaId;
+       }
+
+       /**
+        * @return the routeType
+        */
+       public final OSPFRouteType getRouteType() {
+               return this.routeType;
+       }
+
+       /**
+        * @return the topologyId
+        */
+       public final TopologyIdentifier getTopologyId() {
+               return this.topologyId;
+       }
+
+       /**
+        * @return the topologyNodeInfo
+        */
+       public final TopologyNodeInformation getTopologyNodeInfo() {
+               return this.topologyNodeInfo;
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/MPReach.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/MPReach.java
new file mode 100644 (file)
index 0000000..eda79e0
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import java.util.Set;
+
+/**
+ * 
+ * Common interface for MP_(UN)REACH Attribute.
+ * 
+ * @param <T> Link State NLRI, T represents an Identifier
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc4760">MultiProtocol Extensions for BGP-4</a>
+ */
+public interface MPReach<T> {
+
+       /**
+        * Determines if we have an MP_REACH or MP_UNREACH
+        * 
+        * @return true if the object is MP_REACH, false if its MP_UNREACH
+        */
+       public boolean isReachable();
+
+       /**
+        * 
+        * NLRI without Link-State information are just IP address prefixes, with Link-State inf. it can be also Network
+        * Links or Network Nodes.
+        * 
+        * @return set of objects present in NLRI
+        */
+       public Set<T> getNlri();
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/PathAttribute.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/PathAttribute.java
new file mode 100644 (file)
index 0000000..d557ff3
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.parser.impl;
+
+
+/**
+ * Path Attribute Object defines attributes to routes that are advertised
+ * through BGP. Each Attribute is a triplet <type, length, value>.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.3">BGP-4</a>
+ *
+ */
+public final class PathAttribute {
+
+       /**
+        * Currently known path attributes. Although AS4_PATH and AS4_AGGREGATOR
+        * will not be used, as this is a NEW BGP Speaker, they must be recognizable
+        * and an Update message that contains them, must be parsed properly.
+        *
+        * Added LINK_STATE to conform: <a href="http://tools.ietf.org/html/draft-gredler-idr-ls-distribution-02#section-3.3">LINK_STATE Attribute</a>
+        * Added COMMUNITIES from: <a href="http://tools.ietf.org/html/rfc1997">COMMUNITIES Attribute</a>
+        * Added ORIGINATION_ID and CLUSTER_LIST from: <a href="http://tools.ietf.org/html/rfc4456">BGP Route Reflection</a>
+        */
+       public enum TypeCode {
+               ORIGIN, AS_PATH, NEXT_HOP, MULTI_EXIT_DISC, LOCAL_PREF, AGGREGATOR,
+               ATOMIC_AGGREGATE, MP_REACH_NLRI, MP_UNREACH_NLRI, EXTENDED_COMMUNITIES,
+               AS4_PATH, AS4_AGGREGATOR, LINK_STATE, COMMUNITIES, ORIGINATOR_ID,
+               CLUSTER_LIST;
+
+               /**
+                * Parse typecode from int to enum.
+                *
+                * @param type
+                *            int parsed from byte array
+                * @return enum TypeCode
+                */
+               public static TypeCode parseType(final int type) {
+                       switch (type) {
+                       case 1:
+                               return ORIGIN;
+                       case 2:
+                               return AS_PATH;
+                       case 3:
+                               return NEXT_HOP;
+                       case 4:
+                               return MULTI_EXIT_DISC;
+                       case 5:
+                               return LOCAL_PREF;
+                       case 6:
+                               return ATOMIC_AGGREGATE;
+                       case 7:
+                               return AGGREGATOR;
+                       case 8:
+                               return COMMUNITIES;
+                       case 9:
+                               return ORIGINATOR_ID;
+                       case 10:
+                               return CLUSTER_LIST;
+                       case 14:
+                               return MP_REACH_NLRI;
+                       case 15:
+                               return MP_UNREACH_NLRI;
+                       case 16:
+                               return EXTENDED_COMMUNITIES;
+                       case 17:
+                               return AS4_PATH;
+                       case 18:
+                               return AS4_AGGREGATOR;
+                       case 99:        //TODO: to actual value, after it is approved by IANA
+                               return LINK_STATE;
+                       default:
+                               return null;
+                       }
+               }
+       }
+
+       // Attribute type -------------------------------------------------------
+       /**
+        * Size of the flags field in path attribute, in bytes.
+        */
+       public static final int ATTR_FLAGS_SIZE = 1;
+
+       /**
+        * 0 - Optional bit: attribute is optional (if set to 1) or well-known (if
+        * set to 0)
+        */
+       private final boolean optional;
+
+       /**
+        * 1 - Transitive bit: attribute is transitive (if set to 1) or
+        * non-transitive (if set to 0)
+        */
+       private final boolean transitive;
+
+       /**
+        * 2 - Partial bit: attribute is partial (if set to 1) or complete (if set
+        * to 0)
+        */
+       private final boolean partial;
+
+       /**
+        * 3 - Extended Length bit: attribute length is one octet (if set to 0) or
+        * two octets (if set to 1)
+        */
+       private final boolean extendedLength;
+
+       /**
+        * Size of the field Attribute Type Code, in bytes.
+        */
+       public static final int ATTR_TYPE_CODE_SIZE = 1;
+
+       private TypeCode type;
+
+       // Attribute Length ------------------------------------------------------
+
+       /**
+        * Size of the attribute length field, in bytes. Depends on
+        * extendedLengthBit.
+        */
+       private final int attrLengthSize;
+
+       /**
+        * Length of the attribute value, in bytes.
+        */
+       private int length;
+
+       // -----------------------------------------------------------------------
+
+       /**
+        * Attribute value
+        */
+       private Object value;
+
+       // Constructors ----------------------------------------------------------
+
+       public PathAttribute(final boolean optional, final boolean transitive,
+                       final boolean partial, final boolean extendedLength) {
+               this(null, optional, transitive, partial, extendedLength, null);
+       }
+
+       public PathAttribute(final TypeCode type, final boolean optional,
+                       final boolean transitive, final boolean partial,
+                       final boolean extendedLength, final Object value) {
+               this.type = type;
+               this.optional = optional;
+               this.transitive = transitive;
+               this.partial = partial;
+               this.extendedLength = extendedLength;
+               this.value = value;
+               this.attrLengthSize = (this.extendedLength) ? 2 : 1;
+       }
+
+       // Getters & setters -----------------------------------------------------
+
+       public TypeCode getType() {
+               return this.type;
+       }
+
+       public int getLength() {
+               return this.length;
+       }
+
+       public Object getValue() {
+               return this.value;
+       }
+
+       public int getAttrLengthSize() {
+               return this.attrLengthSize;
+       }
+
+       public void setType(final TypeCode type) {
+               this.type = type;
+       }
+
+       public void setValue(final Object value) {
+               this.value = value;
+       }
+
+       public void setLength(final int length) {
+               this.length = length;
+       }
+
+       public boolean isOptional() {
+               return this.optional;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PathAttribute [optional=");
+               builder.append(this.optional);
+               builder.append(", transitive=");
+               builder.append(this.transitive);
+               builder.append(", partial=");
+               builder.append(this.partial);
+               builder.append(", extendedLength=");
+               builder.append(this.extendedLength);
+               builder.append(", type=");
+               builder.append(this.type);
+               builder.append(", attrLengthSize=");
+               builder.append(this.attrLengthSize);
+               builder.append(", length=");
+               builder.append(this.length);
+               builder.append(", value=");
+               builder.append(this.value);
+               builder.append("]");
+               return builder.toString();
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + this.attrLengthSize;
+               result = prime * result + (this.extendedLength ? 1231 : 1237);
+               result = prime * result + (this.optional ? 1231 : 1237);
+               result = prime * result + (this.partial ? 1231 : 1237);
+               result = prime * result + (this.transitive ? 1231 : 1237);
+               result = prime * result + ((this.type == null) ? 0 : this.type.hashCode());
+               result = prime * result + ((this.value == null) ? 0 : this.value.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PathAttribute other = (PathAttribute) obj;
+               if (this.attrLengthSize != other.attrLengthSize)
+                       return false;
+               if (this.extendedLength != other.extendedLength)
+                       return false;
+               if (this.optional != other.optional)
+                       return false;
+               if (this.partial != other.partial)
+                       return false;
+               if (this.transitive != other.transitive)
+                       return false;
+               if (this.type != other.type)
+                       return false;
+               if (this.value == null) {
+                       if (other.value != null)
+                               return false;
+               } else if (!this.value.equals(other.value))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPNotificationMessageParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPNotificationMessageParser.java
new file mode 100644 (file)
index 0000000..5bb7df5
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl.message;
+
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for BGPNotification message.
+ */
+public final class BGPNotificationMessageParser {
+
+       private static final Logger logger = LoggerFactory.getLogger(BGPNotificationMessageParser.class);
+
+       private static final int ERROR_SIZE = 2; // bytes
+
+       private static class BGPErr {
+               private final int errorCode;
+               private final int errorSubcode;
+
+               public BGPErr(final int errorCode, final int errorSubcode) {
+                       this.errorCode = errorCode;
+                       this.errorSubcode = errorSubcode;
+               }
+
+               public int getErrorCode() {
+                       return this.errorCode;
+               }
+
+               public int getErrorSubcode() {
+                       return this.errorSubcode;
+               }
+       }
+
+       /**
+        * Serializes BGP Notification message.
+        * 
+        * @param msg to be serialized
+        * @return BGP Notification message converted to byte array
+        */
+       public static byte[] put(final BGPNotificationMessage msg) {
+               if (msg == null)
+                       throw new IllegalArgumentException("BGP Notification message cannot be null");
+               logger.trace("Started serializing Notification message: {}", msg);
+
+               final byte[] msgBody = (msg.getData() == null) ? new byte[ERROR_SIZE] : new byte[ERROR_SIZE + msg.getData().length];
+
+               final BGPErr numError = parseBGPError(msg.getError());
+
+               if (numError == null)
+                       throw new IllegalArgumentException("Cannot parse BGP Error: " + msg.getError());
+
+               msgBody[0] = ByteArray.intToBytes(numError.getErrorCode())[Integer.SIZE / Byte.SIZE - 1];
+
+               msgBody[1] = ByteArray.intToBytes(numError.getErrorSubcode())[Integer.SIZE / Byte.SIZE - 1];
+
+               if (msg.getData() != null)
+                       System.arraycopy(msg.getData(), 0, msgBody, ERROR_SIZE, msg.getData().length);
+               logger.trace("Notification message serialized to: {}", Arrays.toString(msgBody));
+               return msgBody;
+       }
+
+       /**
+        * Parses BGP Notification message to bytes.
+        * 
+        * @param bytes byte array to be parsed
+        * @return BGPNotification message
+        * @throws BGPDocumentedException
+        */
+       public static BGPNotificationMessage parse(final byte[] bytes) throws BGPDocumentedException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array cannot be null or empty.");
+               logger.trace("Started parsing of notification message: {}", Arrays.toString(bytes));
+
+               if (bytes.length < ERROR_SIZE)
+                       throw new BGPDocumentedException("Notification message too small.", BGPError.BAD_MSG_LENGTH, ByteArray.intToBytes(bytes.length));
+               final int errorCode = UnsignedBytes.toInt(bytes[0]);
+               final int errorSubcode = UnsignedBytes.toInt(bytes[1]);
+
+               final BGPError err = putBGPError(new BGPErr(errorCode, errorSubcode));
+               byte[] data = null;
+               if (bytes.length > ERROR_SIZE) {
+                       data = ByteArray.subByte(bytes, ERROR_SIZE, bytes.length - ERROR_SIZE);
+               }
+               logger.trace("Notification message was parsed: err = {}, data = {}.", err, Arrays.toString(data));
+               return (data == null) ? new BGPNotificationMessage(err) : new BGPNotificationMessage(err, data);
+       }
+
+       private static BGPErr parseBGPError(final BGPError err) {
+               switch (err) {
+               case CONNECTION_NOT_SYNC:
+                       return new BGPErr(1, 1);
+               case BAD_MSG_LENGTH:
+                       return new BGPErr(1, 2);
+               case BAD_MSG_TYPE:
+                       return new BGPErr(1, 3);
+               case UNSPECIFIC_OPEN_ERROR:
+                       return new BGPErr(2, 0);
+               case VERSION_NOT_SUPPORTED:
+                       return new BGPErr(2, 1);
+               case BAD_PEER_AS:
+                       return new BGPErr(2, 2);
+               case BAD_BGP_ID:
+                       return new BGPErr(2, 3);
+               case OPT_PARAM_NOT_SUPPORTED:
+                       return new BGPErr(2, 4);
+               case HOLD_TIME_NOT_ACC:
+                       return new BGPErr(2, 6);
+               case MALFORMED_ATTR_LIST:
+                       return new BGPErr(3, 1);
+               case WELL_KNOWN_ATTR_NOT_RECOGNIZED:
+                       return new BGPErr(3, 2);
+               case WELL_KNOWN_ATTR_MISSING:
+                       return new BGPErr(3, 3);
+               case ATTR_FLAGS_MISSING:
+                       return new BGPErr(3, 4);
+               case ATTR_LENGTH_ERROR:
+                       return new BGPErr(3, 5);
+               case ORIGIN_ATTR_NOT_VALID:
+                       return new BGPErr(3, 6);
+               case NEXT_HOP_NOT_VALID:
+                       return new BGPErr(3, 8);
+               case OPT_ATTR_ERROR:
+                       return new BGPErr(3, 9);
+               case NETWORK_NOT_VALID:
+                       return new BGPErr(3, 10);
+               case AS_PATH_MALFORMED:
+                       return new BGPErr(3, 11);
+               case HOLD_TIMER_EXPIRED:
+                       return new BGPErr(4, 0);
+               case FSM_ERROR:
+                       return new BGPErr(5, 0);
+               case CEASE:
+                       return new BGPErr(6, 0);
+               default:
+                       return null;
+               }
+       }
+
+       private static BGPError putBGPError(final BGPErr err) {
+               final int e = err.getErrorCode();
+               final int s = err.getErrorSubcode();
+               if (e == 1) {
+                       if (s == 1)
+                               return BGPError.CONNECTION_NOT_SYNC;
+                       if (s == 2)
+                               return BGPError.BAD_MSG_LENGTH;
+                       if (s == 3)
+                               return BGPError.BAD_MSG_TYPE;
+               } else if (e == 2) {
+                       if (s == 0)
+                               return BGPError.UNSPECIFIC_OPEN_ERROR;
+                       if (s == 1)
+                               return BGPError.VERSION_NOT_SUPPORTED;
+                       if (s == 2)
+                               return BGPError.BAD_PEER_AS;
+                       if (s == 3)
+                               return BGPError.BAD_BGP_ID;
+                       if (s == 4)
+                               return BGPError.OPT_PARAM_NOT_SUPPORTED;
+                       if (s == 6)
+                               return BGPError.HOLD_TIME_NOT_ACC;
+               } else if (e == 3) {
+                       if (s == 1)
+                               return BGPError.MALFORMED_ATTR_LIST;
+                       if (s == 2)
+                               return BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED;
+                       if (s == 3)
+                               return BGPError.WELL_KNOWN_ATTR_MISSING;
+                       if (s == 4)
+                               return BGPError.ATTR_FLAGS_MISSING;
+                       if (s == 5)
+                               return BGPError.ATTR_LENGTH_ERROR;
+                       if (s == 6)
+                               return BGPError.ORIGIN_ATTR_NOT_VALID;
+                       if (s == 8)
+                               return BGPError.NEXT_HOP_NOT_VALID;
+                       if (s == 9)
+                               return BGPError.OPT_ATTR_ERROR;
+                       if (s == 10)
+                               return BGPError.NETWORK_NOT_VALID;
+                       if (s == 11)
+                               return BGPError.AS_PATH_MALFORMED;
+               } else if (e == 4)
+                       return BGPError.HOLD_TIMER_EXPIRED;
+               else if (e == 5)
+                       return BGPError.FSM_ERROR;
+               else if (e == 6)
+                       return BGPError.CEASE;
+               throw new IllegalArgumentException("BGP Error code " + e + " and subcode " + s + " not recognized.");
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPOpenMessageParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPOpenMessageParser.java
new file mode 100644 (file)
index 0000000..a16bf7c
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl.message;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.message.open.BGPParameterParser;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for BGP Open message.
+ */
+public final class BGPOpenMessageParser {
+
+       private static final Logger logger = LoggerFactory.getLogger(BGPOpenMessageParser.class);
+
+       private static final int VERSION_SIZE = 1;
+       private static final int AS_SIZE = 2;
+       private static final int HOLD_TIME_SIZE = 2;
+       private static final int BGP_ID_SIZE = 4;
+       private static final int OPT_PARAM_LENGTH_SIZE = 1;
+
+       private static final int MIN_MSG_LENGTH = VERSION_SIZE + AS_SIZE + HOLD_TIME_SIZE + BGP_ID_SIZE + OPT_PARAM_LENGTH_SIZE;
+
+       private BGPOpenMessageParser() {
+
+       }
+
+       /**
+        * Serializes given BGP Open message to byte array, without the header.
+        * 
+        * @param msg BGP Open message to be serialized.
+        * @return BGP Open message converted to byte array
+        */
+       public static byte[] put(final BGPOpenMessage msg) {
+               if (msg == null)
+                       throw new IllegalArgumentException("BGPOpen message cannot be null");
+               logger.trace("Started serializing open message: {}", msg);
+
+               final Map<byte[], Integer> optParams = Maps.newHashMap();
+
+               int optParamsLength = 0;
+
+               if (msg.getOptParams() != null) {
+                       for (final BGPParameter param : msg.getOptParams()) {
+                               final byte[] p = BGPParameterParser.put(param);
+                               optParams.put(p, p.length);
+                               optParamsLength += p.length;
+                       }
+               }
+
+               final byte[] msgBody = (msg.getOptParams() == null || msg.getOptParams().isEmpty()) ? new byte[MIN_MSG_LENGTH]
+                               : new byte[MIN_MSG_LENGTH + optParamsLength];
+
+               int offset = 0;
+
+               msgBody[offset] = ByteArray.intToBytes(BGPOpenMessage.BGP_VERSION)[(Integer.SIZE / Byte.SIZE) - 1];
+               offset += VERSION_SIZE;
+
+               // When our AS number does not fit into two bytes, we report it as AS_TRANS
+               ASNumber openAS = msg.getMyAS();
+               if (openAS.getHighValue() != 0)
+                       openAS = ASNumber.TRANS;
+
+               System.arraycopy(ByteArray.intToBytes(openAS.getLowValue()), 2, msgBody, offset, AS_SIZE);
+               offset += AS_SIZE;
+
+               System.arraycopy(ByteArray.shortToBytes(msg.getHoldTime()), 0, msgBody, offset, HOLD_TIME_SIZE);
+               offset += HOLD_TIME_SIZE;
+
+               System.arraycopy(msg.getBgpId().getAddress(), 0, msgBody, offset, BGP_ID_SIZE);
+               offset += BGP_ID_SIZE;
+
+               msgBody[offset] = ByteArray.intToBytes(optParamsLength)[Integer.SIZE / Byte.SIZE - 1];
+
+               int index = MIN_MSG_LENGTH;
+               if (optParams != null) {
+                       for (final Entry<byte[], Integer> entry : optParams.entrySet()) {
+                               System.arraycopy(entry.getKey(), 0, msgBody, index, entry.getValue());
+                               index += entry.getValue();
+                       }
+               }
+               logger.trace("Open message serialized to: {}", Arrays.toString(msgBody));
+               return msgBody;
+       }
+
+       /**
+        * Parses given byte array to BGP Open message
+        * 
+        * @param bytes byte array representing BGP Open message, without header
+        * @return BGP Open Message
+        * @throws BGPDocumentedException if the parsing was unsuccessful
+        */
+       public static BGPOpenMessage parse(final byte[] bytes) throws BGPDocumentedException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array cannot be null or empty.");
+               logger.trace("Started parsing of open message: {}", Arrays.toString(bytes));
+
+               if (bytes.length < MIN_MSG_LENGTH)
+                       throw new BGPDocumentedException("Open message too small.", BGPError.BAD_MSG_LENGTH, ByteArray.intToBytes(bytes.length));
+               if (UnsignedBytes.toInt(bytes[0]) != BGPOpenMessage.BGP_VERSION)
+                       throw new BGPDocumentedException("BGP Protocol version " + UnsignedBytes.toInt(bytes[0]) + " not supported.", BGPError.VERSION_NOT_SUPPORTED, ByteArray.subByte(
+                                       ByteArray.intToBytes(BGPOpenMessage.BGP_VERSION), 2, 2));
+
+               int offset = VERSION_SIZE;
+               final ASNumber as = new ASNumber(0, ByteArray.bytesToInt(ByteArray.subByte(bytes, offset, AS_SIZE)));
+               offset += AS_SIZE;
+
+               // TODO: BAD_PEER_AS Error: when is an AS unacceptable?
+
+               final short holdTime = ByteArray.bytesToShort(ByteArray.subByte(bytes, offset, HOLD_TIME_SIZE));
+               offset += HOLD_TIME_SIZE;
+               if (holdTime == 1 || holdTime == 2)
+                       throw new BGPDocumentedException("Hold time value not acceptable.", BGPError.HOLD_TIME_NOT_ACC);
+
+               IPv4Address bgpId = null;
+               try {
+                       bgpId = new IPv4Address(ByteArray.subByte(bytes, offset, BGP_ID_SIZE));
+               } catch (final IllegalArgumentException e) {
+                       throw new BGPDocumentedException("BGP Identifier is not a valid IPv4 Address", BGPError.BAD_BGP_ID);
+               }
+               offset += BGP_ID_SIZE;
+
+               final int optLength = UnsignedBytes.toInt(bytes[offset]);
+
+               List<BGPParameter> optParams = Lists.newArrayList();
+               if (optLength > 0) {
+                       try {
+                               optParams = BGPParameterParser.parse(ByteArray.subByte(bytes, MIN_MSG_LENGTH, optLength));
+                       } catch (final BGPParsingException e) {
+                               throw new BGPDocumentedException("Optional parameter not parsed: ." + e.getMessage(), BGPError.UNSPECIFIC_OPEN_ERROR);
+                       }
+               }
+               logger.trace("Open message was parsed: AS = {}, holdTimer = {}, bgpId = {}, optParams = {}", as, holdTime, bgpId, optParams);
+               return new BGPOpenMessage(as, holdTime, bgpId, optParams);
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java
new file mode 100644 (file)
index 0000000..7d665e9
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.parser.impl.message;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateEvent;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
+import org.opendaylight.protocol.bgp.parser.impl.BGPUpdateEventBuilder;
+import org.opendaylight.protocol.bgp.parser.impl.IPv6MP;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute.TypeCode;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.PathAttributeParser;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.Prefix;
+import com.google.common.collect.Lists;
+
+/**
+ * LENGTH fields, that denote the length of the fields with variable length, have fixed SIZE.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.3">BGP-4 Update Message Format</a>
+ * 
+ */
+public class BGPUpdateMessageParser {
+
+       private static Logger logger = LoggerFactory.getLogger(BGPUpdateMessageParser.class);
+
+       /**
+        * Size of the withdrawn_routes_length field, in bytes.
+        */
+       public static final int WITHDRAWN_ROUTES_LENGTH_SIZE = 2;
+
+       /**
+        * Size of the total_path_attr_length field, in bytes.
+        */
+       public static final int TOTAL_PATH_ATTR_LENGTH_SIZE = 2;
+
+       // Constructors -------------------------------------------------------
+
+       public BGPUpdateMessageParser() {
+
+       }
+
+       // Getters & setters --------------------------------------------------
+
+       public static BGPUpdateEvent parse(final byte[] bytes, final int msgLength) throws BGPDocumentedException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array cannot be null or empty.");
+               logger.trace("Started parsing of update message: {}", Arrays.toString(bytes));
+
+               int byteOffset = 0;
+
+               final int withdrawnRoutesLength = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, WITHDRAWN_ROUTES_LENGTH_SIZE));
+               byteOffset += WITHDRAWN_ROUTES_LENGTH_SIZE;
+
+               final BGPUpdateEventBuilder eventBuilder = new BGPUpdateEventBuilder();
+               eventBuilder.setWithdrawnRoutesLength(withdrawnRoutesLength);
+
+               Set<Prefix<IPv4Address>> withdrawnRoutes;
+               if (withdrawnRoutesLength > 0) {
+                       withdrawnRoutes = IPv4.FAMILY.prefixListForBytes(ByteArray.subByte(bytes, byteOffset, withdrawnRoutesLength));
+                       byteOffset += withdrawnRoutesLength;
+               } else {
+                       withdrawnRoutes = Collections.emptySet();
+               }
+               eventBuilder.setWithdrawnRoutes(withdrawnRoutes);
+
+               final int totalPathAttrLength = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TOTAL_PATH_ATTR_LENGTH_SIZE));
+               byteOffset += TOTAL_PATH_ATTR_LENGTH_SIZE;
+               eventBuilder.setTotalPathAttrLength(totalPathAttrLength);
+
+               if (withdrawnRoutesLength + totalPathAttrLength + BGPMessageHeader.COMMON_HEADER_LENGTH > msgLength)
+                       throw new BGPDocumentedException("Message length inconsistent with withdrawn router length.", BGPError.MALFORMED_ATTR_LIST);
+
+               if (withdrawnRoutesLength == 0 && totalPathAttrLength == 0) {
+                       final BGPUpdateSynchronized event = new BGPUpdateSynchronized() {
+
+                               private static final long serialVersionUID = 5709361453437508337L;
+
+                               @Override
+                               public BGPTableType getTableType() {
+                                       return new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+                               }
+                       };
+                       return event;
+               }
+
+               List<PathAttribute> pathAttributes;
+               if (totalPathAttrLength > 0) {
+                       pathAttributes = parsePathAttributes(ByteArray.subByte(bytes, byteOffset, totalPathAttrLength));
+                       byteOffset += totalPathAttrLength;
+                       if (pathAttributes.get(0).getType() == TypeCode.MP_UNREACH_NLRI && totalPathAttrLength == 6) {
+                               if (pathAttributes.get(0).getValue() instanceof IPv6MP) {
+                                       final BGPUpdateEvent event = new BGPUpdateSynchronized() {
+
+                                               private static final long serialVersionUID = -6026212683738125407L;
+
+                                               @Override
+                                               public BGPTableType getTableType() {
+                                                       return new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.Unicast);
+                                               }
+
+                                       };
+                                       return event;
+                               } else if (pathAttributes.get(0).getValue() == null) {
+                                       final BGPUpdateSynchronized event = new BGPUpdateSynchronized() {
+
+                                               private static final long serialVersionUID = 5888562784007786559L;
+
+                                               @Override
+                                               public BGPTableType getTableType() {
+                                                       return new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Unicast);
+                                               }
+
+                                       };
+                                       return event;
+                               }
+                       }
+               } else {
+                       pathAttributes = Collections.emptyList();
+               }
+               eventBuilder.setPathAttributes(pathAttributes);
+
+               final Set<Prefix<IPv4Address>> nlri = IPv4.FAMILY.prefixListForBytes(ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset));
+               eventBuilder.setNlri(nlri);
+
+               try {
+                       logger.trace("Update message was parsed.");
+                       return eventBuilder.buildEvent();
+               } catch (final BGPParsingException e) {
+                       throw new BGPDocumentedException("Parsing unsuccessful: {}" + e.getMessage(), BGPError.MALFORMED_ATTR_LIST);
+               }
+       }
+
+       /**
+        * Parse different Path Attributes from given bytes.
+        * 
+        * @param bytes byte array to be parsed
+        * @return list of Path Attributes
+        * @throws BGPParsingException
+        */
+       private static List<PathAttribute> parsePathAttributes(byte[] bytes) throws BGPDocumentedException {
+               if (bytes.length == 0) {
+                       return Collections.emptyList();
+               }
+               final List<PathAttribute> list = Lists.newArrayList();
+               while (bytes.length != 0) {
+                       PathAttribute attr;
+                       try {
+                               attr = PathAttributeParser.parseAttribute(bytes);
+                               bytes = ByteArray.cutBytes(bytes,
+                                               PathAttribute.ATTR_FLAGS_SIZE + PathAttribute.ATTR_TYPE_CODE_SIZE + attr.getAttrLengthSize() + attr.getLength());
+                               list.add(attr);
+                       } catch (final BGPParsingException e) {
+                               logger.warn("Could not parse BGP attributes: {}", e.getMessage(), e);
+                               throw new BGPDocumentedException("Could not parse BGP attributes.", BGPError.MALFORMED_ATTR_LIST);
+                       }
+               }
+               return list;
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/BGPParameterParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/BGPParameterParser.java
new file mode 100644 (file)
index 0000000..4c2cbe1
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl.message.open;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.parameter.CapabilityParameter;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for parameters in BGP Open message.
+ */
+public final class BGPParameterParser {
+
+       private static final Logger logger = LoggerFactory.getLogger(BGPParameterParser.class);
+
+       private static final int TYPE_SIZE = 1; // bytes
+       private static final int LENGTH_SIZE = 1; // bytes
+       private static final int CAPABILITIES_OPT_PARAM_TYPE = 2;
+
+       private BGPParameterParser() {
+
+       }
+
+       /**
+        * Serializes given BGP Parameter to byte array. Currently supported only Capability parameters.
+        * 
+        * @param param BGP Parameter to be serialized
+        * @return BGP Parameter converted to byte array
+        */
+       public static byte[] put(final BGPParameter param) {
+               if (param == null)
+                       throw new IllegalArgumentException("BGP Parameter cannot be null");
+               logger.trace("Started serializing BGPParameter: {}", param);
+
+               byte[] value = null;
+
+               if (param instanceof CapabilityParameter) {
+                       value = CapabilityParameterParser.put((CapabilityParameter) param);
+               } else {
+                       logger.debug("BGP Parameter not supported.");
+                       return new byte[] {};
+               }
+
+               final byte[] bytes = new byte[TYPE_SIZE + LENGTH_SIZE + value.length];
+               System.arraycopy(ByteArray.intToBytes(param.getType()), 3, bytes, 0, TYPE_SIZE);
+               System.arraycopy(ByteArray.intToBytes(value.length), 3, bytes, TYPE_SIZE, LENGTH_SIZE);
+               System.arraycopy(value, 0, bytes, TYPE_SIZE + LENGTH_SIZE, value.length);
+               logger.trace("BGP Parameter serialized to: {}", Arrays.toString(bytes));
+               return bytes;
+       }
+
+       /**
+        * Parses given byte array to a list of BGP Parameters. Currently supporting only Capability parameters.
+        * 
+        * @param bytes byte array representing BGP Parameters
+        * @return list of BGP Parameters
+        * @throws BGPParsingException if the parsing was unsuccessful
+        */
+       public static List<BGPParameter> parse(final byte[] bytes) throws BGPParsingException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array cannot be null or empty.");
+               logger.trace("Started parsing of BGP parameter: {}", Arrays.toString(bytes));
+               int byteOffset = 0;
+               final List<BGPParameter> params = Lists.newArrayList();
+               while (byteOffset < bytes.length) {
+                       final int paramType = UnsignedBytes.toInt(bytes[byteOffset++]);
+                       final int paramLength = UnsignedBytes.toInt(bytes[byteOffset++]);
+                       if (paramType == CAPABILITIES_OPT_PARAM_TYPE) {
+                               final BGPParameter param = CapabilityParameterParser.parse(ByteArray.subByte(bytes, byteOffset, paramLength));
+                               if (param != null)
+                                       params.add(param);
+                       } else
+                               logger.debug("BGP Parameter not recognized. Type: {}", paramType);
+                       byteOffset += paramLength;
+               }
+               logger.trace("Parsed BGP parameters: {}", Arrays.toString(params.toArray()));
+               return params;
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/CapabilityParameterParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/CapabilityParameterParser.java
new file mode 100644 (file)
index 0000000..d3af441
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl.message.open;
+
+import java.util.Arrays;
+import java.util.Map.Entry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.MPReachParser;
+import org.opendaylight.protocol.bgp.parser.parameter.AS4BytesCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.CapabilityParameter;
+import org.opendaylight.protocol.bgp.parser.parameter.GracefulCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for BGP Capability Parameter.
+ */
+public final class CapabilityParameterParser {
+
+       private static final Logger logger = LoggerFactory.getLogger(CapabilityParameterParser.class);
+
+       private static final int CODE_SIZE = 1; // bytes
+       private static final int LENGTH_SIZE = 1; // bytes
+       private static final int AFI_SIZE = 2; // bytes
+       private static final int SAFI_SIZE = 1; // bytes
+
+       private CapabilityParameterParser() {
+
+       }
+
+       /**
+        * Serializes given BGP Capability Parameter to byte array.
+        * 
+        * @param param BGP Capability to be serialized
+        * @return BGP Capability converted to byte array
+        */
+       public static byte[] put(final CapabilityParameter cap) {
+               if (cap == null)
+                       throw new IllegalArgumentException("BGP Capability cannot be null");
+               logger.trace("Started serializing BGP Capability: {}", cap);
+               byte[] value = null;
+               if (cap instanceof MultiprotocolCapability) {
+                       value = putMultiProtocolParameterValue((MultiprotocolCapability) cap);
+               } else if (cap instanceof GracefulCapability) {
+                       value = putGracefulParameterValue((GracefulCapability) cap);
+               } else if (cap instanceof AS4BytesCapability) {
+                       value = putAS4BytesParameterValue((AS4BytesCapability) cap);
+               }
+               final byte[] bytes = new byte[CODE_SIZE + LENGTH_SIZE + value.length];
+               bytes[0] = ByteArray.intToBytes(cap.getCode())[Integer.SIZE / Byte.SIZE - 1];
+               bytes[1] = ByteArray.intToBytes(value.length)[Integer.SIZE / Byte.SIZE - 1];
+               System.arraycopy(value, 0, bytes, CODE_SIZE + LENGTH_SIZE, value.length);
+               logger.trace("BGP Parameter serialized to: {}", Arrays.toString(bytes));
+               return bytes;
+       }
+
+       /**
+        * Parses given byte array to Capability Parameter. Only Multiprotocol capability is supported.
+        * 
+        * @param bytes byte array representing BGP Parameters
+        * @return list of BGP Parameters
+        * @throws BGPParsingException if the parsing was unsuccessful
+        */
+       public static CapabilityParameter parse(final byte[] bytes) throws BGPParsingException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array cannot be null or empty.");
+               logger.trace("Started parsing of BGP Capability: {}", Arrays.toString(bytes));
+               int byteOffset = 0;
+               final int capCode = UnsignedBytes.toInt(bytes[byteOffset++]);
+               final int capLength = UnsignedBytes.toInt(bytes[byteOffset++]);
+               if (capCode == MultiprotocolCapability.CODE) {
+                       logger.trace("Parsed BGP Capability.");
+                       return parseMultiProtocolParameterValue(ByteArray.subByte(bytes, byteOffset, capLength));
+               } else if (capCode == AS4BytesCapability.CODE) {
+                       logger.trace("Parsed AS4B Capability.");
+                       return parseAS4BParameterValue(ByteArray.subByte(bytes, byteOffset, capLength));
+               } else
+                       logger.debug("Only Multiprotocol Capability Parameter is supported. Received code {}", capCode);
+               return null;
+       }
+
+       private static byte[] putGracefulParameterValue(final GracefulCapability param) {
+               final int RESTART_FLAGS_SIZE = 4; // bits
+               final int TIMER_SIZE = 12; // bits
+               final int AFI_SIZE = 2; // bytes
+               final int SAFI_SIZE = 1; // bytes
+               final int AF_FLAGS_SIZE = 1; // bytes
+               final byte[] bytes = new byte[(RESTART_FLAGS_SIZE + TIMER_SIZE + (AFI_SIZE * Byte.SIZE + SAFI_SIZE * Byte.SIZE + AF_FLAGS_SIZE
+                               * Byte.SIZE)
+                               * param.getTableTypes().size())
+                               / Byte.SIZE];
+               if (param.isRestartFlag())
+                       bytes[0] = (byte) 0x80;
+               int index = (RESTART_FLAGS_SIZE + TIMER_SIZE) / Byte.SIZE;
+               for (final Entry<BGPTableType, Boolean> entry : param.getTableTypes().entrySet()) {
+                       final byte[] a = putAfi(entry.getKey().getAddressFamily());
+                       final byte s = putSafi(entry.getKey().getSubsequentAddressFamily());
+                       final byte f = (entry.getValue()) ? (byte) 0x80 : (byte) 0x00;
+                       System.arraycopy(a, 0, bytes, index, AFI_SIZE);
+                       index += AFI_SIZE;
+                       bytes[index] = s;
+                       index += SAFI_SIZE;
+                       bytes[index] = f;
+                       index += AF_FLAGS_SIZE;
+               }
+               return bytes;
+       }
+
+       private static byte[] putMultiProtocolParameterValue(final MultiprotocolCapability param) {
+               final byte[] a = putAfi(param.getAfi());
+               final byte s = putSafi(param.getSafi());
+
+               final byte[] bytes = new byte[AFI_SIZE + SAFI_SIZE + 1]; // 2 byte is reserved 2B AFI + 1B Reserved + 1B SAFI
+               System.arraycopy(a, 0, bytes, 0, AFI_SIZE);
+               bytes[AFI_SIZE + 1] = s; // +1 = reserved
+               return bytes;
+       }
+
+       private static byte[] putAS4BytesParameterValue(final AS4BytesCapability param) {
+               return ByteArray.subByte(ByteArray.longToBytes(param.getASNumber().getAsn()), 4, 4);
+       }
+
+       private static MultiprotocolCapability parseMultiProtocolParameterValue(final byte[] bytes) throws BGPParsingException {
+               final BGPAddressFamily afi = MPReachParser.parseAfi(ByteArray.bytesToInt(ByteArray.subByte(bytes, 0, AFI_SIZE)));
+               final BGPSubsequentAddressFamily safi = MPReachParser.parseSafi(ByteArray.bytesToInt(ByteArray.subByte(bytes, AFI_SIZE + 1,
+                               SAFI_SIZE)));
+               return new MultiprotocolCapability(new BGPTableType(afi, safi));
+       }
+
+       private static AS4BytesCapability parseAS4BParameterValue(final byte[] bytes) {
+               return new AS4BytesCapability(new ASNumber(ByteArray.bytesToLong(bytes)));
+       }
+
+       static byte[] putAfi(final BGPAddressFamily afi) {
+               final byte[] a = ByteArray.intToBytes(serializeAfi(afi));
+               return ByteArray.subByte(a, Integer.SIZE / Byte.SIZE - AFI_SIZE, AFI_SIZE);
+       }
+
+       static byte putSafi(final BGPSubsequentAddressFamily safi) {
+               final byte[] a = ByteArray.intToBytes(serializeSafi(safi));
+               return ByteArray.subByte(a, Integer.SIZE / Byte.SIZE - SAFI_SIZE, SAFI_SIZE)[0];
+       }
+
+       private static int serializeSafi(final BGPSubsequentAddressFamily type) {
+               switch (type) {
+               case Unicast:
+                       return 1;
+               case MPLSLabeledVPN:
+                       return 128;
+               case Linkstate:
+                       return MPReachParser.LS_SAFI;
+               }
+               return 0;
+       }
+
+       private static int serializeAfi(final BGPAddressFamily type) {
+               switch (type) {
+               case IPv4:
+                       return 1;
+               case IPv6:
+                       return 2;
+               case LinkState:
+                       return MPReachParser.LS_AFI;
+               }
+               return 0;
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AsPathSegmentParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AsPathSegmentParser.java
new file mode 100644 (file)
index 0000000..536efd9
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.parser.impl.message.update;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ *
+ * Representation of one AS Path Segment. It is, in fact, a TLV, but the length
+ * field is representing the count of AS Numbers in the collection (in its
+ * value). If the segment is of type AS_SEQUENCE, the collection is a List, if
+ * AS_SET, the collection is a Set.
+ *
+ */
+public class AsPathSegmentParser {
+
+       public static final int TYPE_LENGTH = 1; // bytes
+
+       public static final int LENGTH_SIZE = 1; // bytes
+
+       public static final int AS_NUMBER_LENGTH = 4; // bytes
+
+       /**
+        * Possible types of AS Path segments.
+        */
+       public enum SegmentType {
+               AS_SEQUENCE, AS_SET
+       }
+
+       private AsPathSegmentParser() {
+
+       }
+
+       static SegmentType parseType(final int type) {
+               switch (type) {
+               case 1:
+                       return SegmentType.AS_SET;
+               case 2:
+                       return SegmentType.AS_SEQUENCE;
+               default:
+                       return null;
+               }
+       }
+
+       static Collection<ASNumber> parseAsPathSegment(final SegmentType type,
+                       final int count, final byte[] bytes) {
+               final Collection<ASNumber> coll = (type == SegmentType.AS_SEQUENCE) ? new ArrayList<ASNumber>()
+                               : new HashSet<ASNumber>();
+               int byteOffset = 0;
+               for (int i = 0; i < count; i++) {
+                       coll.add(new ASNumber(ByteArray.bytesToLong(ByteArray.subByte(
+                                       bytes, byteOffset, AS_NUMBER_LENGTH))));
+                       byteOffset += AS_NUMBER_LENGTH;
+               }
+               return coll;
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesParser.java
new file mode 100644 (file)
index 0000000..c222b6c
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.parser.impl.message.update;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.bgp.concepts.ASSpecificExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.Inet4SpecificExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.OpaqueExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.RouteOriginCommunity;
+import org.opendaylight.protocol.bgp.concepts.RouteTargetCommunity;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for Extended Communities Path Attribute.
+ */
+public class CommunitiesParser {
+
+       public static final int EXTENDED_COMMUNITY_LENGTH = 8; // bytes
+
+       public static final int COMMUNITY_LENGTH = 4; // bytes
+
+       private static final int TYPE_LENGTH = 2; // bytes
+
+       private static final int AS_NUMBER_LENGTH = 2; // bytes
+
+       private static final int AS_LOCAL_ADMIN_LENGTH = 4; // bytes
+
+       private CommunitiesParser() {
+
+       }
+
+       /**
+        * Parse known Community, if unknown, a new one will be created.
+        * 
+        * @param bytes byte array to be parsed
+        * @return new Community
+        * @throws BGPDocumentedException
+        */
+       static Community parseCommunity(final byte[] bytes) throws BGPDocumentedException {
+               if (bytes.length != COMMUNITY_LENGTH)
+                       throw new BGPDocumentedException("Community with wrong length: " + bytes.length, BGPError.OPT_ATTR_ERROR);
+               if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x01 })) {
+                       return Community.NO_EXPORT;
+               } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x02 })) {
+                       return Community.NO_ADVERTISE;
+               } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x03 })) {
+                       return Community.NO_EXPORT_SUBCONFED;
+               }
+               return new Community(new ASNumber(ByteArray.bytesToLong(Arrays.copyOfRange(bytes, 0, AS_NUMBER_LENGTH))), ByteArray.bytesToInt(Arrays.copyOfRange(
+                               bytes, AS_NUMBER_LENGTH, AS_NUMBER_LENGTH + AS_NUMBER_LENGTH)));
+       }
+
+       /**
+        * Parse Extended Community according to their type.
+        * 
+        * @param bytes byte array to be parsed
+        * @return new Specific Extended Community
+        * @throws BGPDocumentedException if the type is not recognized
+        */
+       @VisibleForTesting
+       public static ExtendedCommunity parseExtendedCommunity(final byte[] bytes) throws BGPDocumentedException {
+               // final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, 0, TYPE_LENGTH));
+               final int type = UnsignedBytes.toInt(bytes[0]);
+               final int subType = UnsignedBytes.toInt(bytes[1]);
+               final byte[] value = ByteArray.subByte(bytes, TYPE_LENGTH, bytes.length - TYPE_LENGTH);
+               switch (type) {
+               case 0:
+                       if (subType == 2) {
+                               return new RouteTargetCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+                                               value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+                       } else if (subType == 3) {
+                               return new RouteOriginCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+                                               value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+                       } else
+                               return new ASSpecificExtendedCommunity(false, subType, new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0,
+                                               AS_NUMBER_LENGTH))), ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+               case 40: // 01000000
+                       return new ASSpecificExtendedCommunity(true, subType, new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0,
+                                       AS_NUMBER_LENGTH))), ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+               case 2:
+                       if (subType == 2) {
+                               return new RouteTargetCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+                                               value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+                       } else if (subType == 3) {
+                               return new RouteOriginCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+                                               value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+                       } else
+                               throw new BGPDocumentedException("Could not parse Extended Community subtype: " + subType, BGPError.OPT_ATTR_ERROR);
+               case 1:
+                       if (subType == 2) {
+                               return new RouteTargetCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+                                               value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+                       } else if (subType == 3) {
+                               return new RouteOriginCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+                                               value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+                       } else
+                               return new Inet4SpecificExtendedCommunity(false, subType, new IPv4Address(ByteArray.subByte(value, 0, 4)), ByteArray.subByte(
+                                               value, 4, 2));
+               case 41: // 01000001
+                       return new Inet4SpecificExtendedCommunity(true, subType, new IPv4Address(ByteArray.subByte(value, 0, 4)), ByteArray.subByte(
+                                       value, 4, 2));
+               case 3:
+                       return new OpaqueExtendedCommunity(false, subType, value);
+               case 43: // 01000011
+                       return new OpaqueExtendedCommunity(true, subType, value);
+               default:
+                       throw new BGPDocumentedException("Could not parse Extended Community type: " + type, BGPError.OPT_ATTR_ERROR);
+               }
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LinkStateParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LinkStateParser.java
new file mode 100644 (file)
index 0000000..5049483
--- /dev/null
@@ -0,0 +1,801 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl.message.update;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedSet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.BGPLinkMP;
+import org.opendaylight.protocol.bgp.parser.impl.BGPNodeMP;
+import org.opendaylight.protocol.bgp.parser.impl.ByteList;
+import org.opendaylight.protocol.bgp.parser.impl.MPReach;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.bgp.linkstate.AdministrativeGroup;
+import org.opendaylight.protocol.bgp.linkstate.AreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.DomainIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ExtendedRouteTag;
+import org.opendaylight.protocol.bgp.linkstate.IPv4InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv4RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv6InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv6RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISLANIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISRouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkAnchor;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.MPLSProtocol;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFInterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFPrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFRouteType;
+import org.opendaylight.protocol.bgp.linkstate.OSPFRouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFv3LANIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.RouteTag;
+import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+import org.opendaylight.protocol.bgp.linkstate.UnnumberedLinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISNetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.OSPFNetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv6PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkImpl;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeImpl;
+import com.google.common.base.Charsets;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for Link State information.
+ * 
+ * @see <a href="http://tools.ietf.org/html/draft-gredler-idr-ls-distribution-01">BGP-LS draft</a>
+ */
+public class LinkStateParser {
+
+       private static final Logger logger = LoggerFactory.getLogger(LinkStateParser.class);
+
+       private static final int TYPE_LENGTH = 2;
+
+       private static final int LENGTH_SIZE = 2;
+
+       private static final int ROUTE_DISTINGUISHER_LENGTH = 8;
+
+       private static final int PROTOCOL_ID_LENGTH = 1;
+
+       private static final int IDENTIFIER_LENGTH = 8;
+
+       private static final Set<Integer> nodeTlvs = Sets.newHashSet(263, 1024, 1025, 1026, 1027, 1028, 1029);
+
+       private static final Set<Integer> linkTlvs = Sets.newHashSet(1028, 1029, 1030, 1031, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095,
+                       1096, 1097, 1098);
+
+       private static final Set<Integer> prefixTlvs = Sets.newHashSet(1152, 1153, 1154, 1155, 1156, 1157);
+
+       private enum NlriType {
+               LinkNLRI, NodeNLRI, IPv4Prefixes, IPv6Prefixes
+       }
+
+       private LinkStateParser() {
+       }
+
+       /**
+        * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
+        * 
+        * @param reachable
+        * @param safi
+        * @param bytes
+        * @return BGPLinkMP or BGPNodeMP
+        * @throws BGPParsingException
+        */
+       protected static MPReach<?> parseLSNlri(final boolean reachable, final BGPSubsequentAddressFamily safi, final NextHop<?> nextHop,
+                       final byte[] bytes) throws BGPParsingException {
+               if (bytes.length == 0)
+                       return null;
+               int byteOffset = 0;
+               final Set<LinkIdentifier> links = Sets.newHashSet();
+               final Set<NodeIdentifier> nodes = Sets.newHashSet();
+               final Set<PrefixIdentifier<?>> descs = Sets.newHashSet();
+
+               long identifier = 0;
+               SourceProtocol sp = null;
+
+               while (byteOffset != bytes.length) {
+                       final NlriType type = parseNLRItype(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH)));
+                       byteOffset += TYPE_LENGTH;
+                       // length means total length of the tlvs including route distinguisher not including the type field
+                       final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+                       byteOffset += LENGTH_SIZE;
+                       if (safi == BGPSubsequentAddressFamily.MPLSLabeledVPN) {
+                               // this parses route distinguisher
+                               ByteArray.bytesToLong(ByteArray.subByte(bytes, byteOffset, ROUTE_DISTINGUISHER_LENGTH));
+                               byteOffset += ROUTE_DISTINGUISHER_LENGTH;
+                       }
+                       // parse source protocol
+                       sp = parseProtocolId(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, PROTOCOL_ID_LENGTH)));
+                       byteOffset += PROTOCOL_ID_LENGTH;
+
+                       // parse identifier
+                       identifier = ByteArray.bytesToLong(ByteArray.subByte(bytes, byteOffset, IDENTIFIER_LENGTH));
+                       byteOffset += IDENTIFIER_LENGTH;
+
+                       // if we are dealing with linkstate nodes/links, parse local node descriptor
+                       NodeIdentifier localDescriptor = null;
+                       int locallength = 0;
+                       final int localtype = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+                       byteOffset += TYPE_LENGTH;
+                       locallength = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+                       byteOffset += LENGTH_SIZE;
+                       if (localtype == 256) {
+                               localDescriptor = parseNodeDescriptors(ByteArray.subByte(bytes, byteOffset, locallength));
+                       }
+                       byteOffset += locallength;
+                       final int restLength = length - ((safi == BGPSubsequentAddressFamily.MPLSLabeledVPN) ? ROUTE_DISTINGUISHER_LENGTH : 0)
+                                       - PROTOCOL_ID_LENGTH - IDENTIFIER_LENGTH - TYPE_LENGTH - LENGTH_SIZE - locallength;
+                       logger.debug("Restlength {}", restLength);
+                       switch (type) {
+                       case LinkNLRI:
+                               links.add(parseLink(localDescriptor, sp, ByteArray.subByte(bytes, byteOffset, restLength)));
+                               break;
+                       case IPv4Prefixes:
+                       case IPv6Prefixes:
+                               descs.add(parsePrefixDescriptors(localDescriptor, ByteArray.subByte(bytes, byteOffset, restLength)));
+                               break;
+                       case NodeNLRI:
+                               // node nlri is already parsed as it contains only the common fields for node and link nlri
+                               nodes.add(localDescriptor);
+                               break;
+                       }
+                       byteOffset += restLength;
+               }
+               if (!links.isEmpty())
+                       return new BGPLinkMP(identifier, sp, reachable, links);
+               else if (!nodes.isEmpty())
+                       return new BGPNodeMP(identifier, sp, reachable, nodes);
+               // else if (!descs.isEmpty())
+               // return new BGPIPv4PrefixMP(identifier, sp, descs, reachable);
+               return null;
+       }
+
+       protected static Map<Integer, ByteList> parseLinkState(final byte[] bytes) {
+               final Map<Integer, ByteList> map = new HashMap<Integer, ByteList>();
+               int byteOffset = 0;
+               while (byteOffset != bytes.length) {
+                       final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+                       byteOffset += TYPE_LENGTH;
+                       final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+                       byteOffset += LENGTH_SIZE;
+                       final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
+                       ByteList values = map.containsKey(type) ? values = map.get(type) : new ByteList();
+                       values.add(value);
+                       map.put(type, values);
+                       byteOffset += length;
+               }
+               return map;
+       }
+
+       public static boolean verifyLink(final Set<Integer> keys) {
+               for (final Integer i : keys)
+                       if (!linkTlvs.contains(i)) {
+                               logger.warn("Invalid link attribute {}", i);
+                               return false;
+                       }
+               return true;
+       }
+
+       public static boolean verifyNode(final Set<Integer> keys) {
+               for (final Integer i : keys)
+                       if (!nodeTlvs.contains(i)) {
+                               logger.warn("Invalid node attribute {}", i);
+                               return false;
+                       }
+               return true;
+       }
+
+       public static boolean verifyPrefix(final Set<Integer> keys) {
+               for (final Integer i : keys)
+                       if (!prefixTlvs.contains(i)) {
+                               logger.warn("Invalid prefix attribute {}", i);
+                               return false;
+                       }
+               return true;
+       }
+
+       /**
+        * Parse protocol ID from int to enum
+        * 
+        * @param protocolId int parsed from byte array
+        * @return enum SourceProtocol
+        * @throws BGPParsingException if the type is unrecognized
+        */
+       private static SourceProtocol parseProtocolId(final int protocolId) throws BGPParsingException {
+               switch (protocolId) {
+               case 0:
+                       return SourceProtocol.Unknown;
+               case 1:
+                       return SourceProtocol.ISISLevel1;
+               case 2:
+                       return SourceProtocol.ISISLevel2;
+               case 3:
+                       return SourceProtocol.OSPF;
+               case 4:
+                       return SourceProtocol.Direct;
+               case 5:
+                       return SourceProtocol.Static;
+               default:
+                       throw new BGPParsingException("Unknown Source Protocol ID: " + protocolId);
+               }
+       }
+
+       private static OSPFRouteType parseRouteType(final int type) throws BGPParsingException {
+               switch (type) {
+               case 0:
+                       return null; // for IS-IS it needs to be 0
+               case 1:
+                       return OSPFRouteType.Intra_Area;
+               case 2:
+                       return OSPFRouteType.Inter_Area;
+               case 3:
+                       return OSPFRouteType.External1;
+               case 4:
+                       return OSPFRouteType.External2;
+               case 5:
+                       return OSPFRouteType.NSSA1;
+               case 6:
+                       return OSPFRouteType.NSSA2;
+               default:
+                       throw new BGPParsingException("Unknown OSPF Route Type: " + type);
+               }
+       }
+
+       private static LinkIdentifier parseLink(final NodeIdentifier local, final SourceProtocol spi, final byte[] bytes)
+                       throws BGPParsingException {
+               int byteOffset = 0;
+               final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+               byteOffset += TYPE_LENGTH;
+               final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+               byteOffset += LENGTH_SIZE;
+               NodeIdentifier remote = null;
+               if (type == 257) {
+                       remote = parseNodeDescriptors(ByteArray.subByte(bytes, byteOffset, length));
+                       byteOffset += length;
+               }
+
+               return parseLinkDescriptors(local, remote, ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset));
+       }
+
+       /**
+        * Parse Link Descriptors.
+        * 
+        * @param topology
+        * @param localAnchor
+        * @param remoteAnchor
+        * @param bytes
+        * @return
+        * @throws BGPParsingException
+        */
+       private static LinkIdentifier parseLinkDescriptors(final NodeIdentifier local, final NodeIdentifier remote, final byte[] bytes)
+                       throws BGPParsingException {
+               int byteOffset = 0;
+               final List<InterfaceIdentifier> localIdentifiers = Lists.newArrayList();
+               final List<InterfaceIdentifier> remoteIdentifiers = Lists.newArrayList();
+               TopologyIdentifier topId = null;
+               while (byteOffset != bytes.length) {
+                       final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+                       byteOffset += TYPE_LENGTH;
+                       final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+                       byteOffset += LENGTH_SIZE;
+                       final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
+                       logger.debug("Parsing Link Descriptor: {}", Arrays.toString(value));
+                       switch (type) {
+                       case 258:
+                               final UnnumberedLinkIdentifier l = new UnnumberedLinkIdentifier(ByteArray.bytesToLong(ByteArray.subByte(value, 0, 4)));
+                               final UnnumberedLinkIdentifier r = new UnnumberedLinkIdentifier(ByteArray.bytesToLong(ByteArray.subByte(value, 4, 4)));
+                               localIdentifiers.add(l);
+                               remoteIdentifiers.add(r);
+                               logger.trace("Parsed link local {} remote {} Identifiers.", local, remote);
+                               break;
+                       case 259:
+                               final IPv4InterfaceIdentifier lipv4 = new IPv4InterfaceIdentifier(new IPv4Address(value));
+                               localIdentifiers.add(lipv4);
+                               logger.trace("Parsed IPv4 interface address {}.", lipv4);
+                               break;
+                       case 260:
+                               final IPv4InterfaceIdentifier ripv4 = new IPv4InterfaceIdentifier(new IPv4Address(value));
+                               remoteIdentifiers.add(ripv4);
+                               logger.trace("Parsed IPv4 neighbor address {}.", ripv4);
+                               break;
+                       case 261:
+                               final IPv6InterfaceIdentifier lipv6 = new IPv6InterfaceIdentifier(new IPv6Address(value));
+                               localIdentifiers.add(lipv6);
+                               logger.trace("Parsed IPv6 interface address {}.", lipv6);
+                               break;
+                       case 262:
+                               final IPv6InterfaceIdentifier ripv6 = new IPv6InterfaceIdentifier(new IPv6Address(value));
+                               remoteIdentifiers.add(ripv6);
+                               logger.trace("Parsed IPv6 neighbor address {}.", ripv6);
+                               break;
+                       case 263:
+                               topId = new TopologyIdentifier(ByteArray.bytesToLong(value) & 0x3fff);
+                               logger.trace("Parsed topology identifier {}.", topId);
+                               break;
+                       default:
+                               throw new BGPParsingException("Link Descriptor not recognized, type: " + type);
+                       }
+                       byteOffset += length;
+               }
+               logger.debug("Finished parsing Link descriptors.");
+               if (localIdentifiers.size() != 1)
+                       throw new BGPParsingException("Invalid number of local interface identifiers.");
+               final LinkAnchor localAnchor = new LinkAnchor(local, localIdentifiers.get(0));
+               LinkAnchor remoteAnchor = null;
+               if (remoteIdentifiers.size() > 0) {
+                       remoteAnchor = new LinkAnchor(remote, remoteIdentifiers.get(0));
+               } else
+                       remoteAnchor = new LinkAnchor(remote, null);
+               return new LinkIdentifier(topId, localAnchor, remoteAnchor);
+       }
+
+       /**
+        * Parse Node Descriptors. There can be only one TLV present from each type.
+        * 
+        * @param spi
+        * @param bytes
+        * @return
+        * @throws BGPParsingException
+        */
+       private static NodeIdentifier parseNodeDescriptors(final byte[] bytes) throws BGPParsingException {
+               int byteOffset = 0;
+               ASNumber asnumber = null;
+               DomainIdentifier bgpId = null;
+               AreaIdentifier ai = null;
+               RouterIdentifier routerId = null;
+               while (byteOffset != bytes.length) {
+                       final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+                       byteOffset += TYPE_LENGTH;
+                       final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+                       byteOffset += LENGTH_SIZE;
+                       final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
+                       logger.debug("Parsing Node Descriptor: {}", Arrays.toString(value));
+                       switch (type) {
+                       case 512:
+                               asnumber = new ASNumber(ByteArray.bytesToLong(value));
+                               logger.trace("Parsed AS number {}", asnumber);
+                               break;
+                       case 513:
+                               bgpId = new DomainIdentifier(value);
+                               logger.trace("Parsed bgpId {}", bgpId);
+                               break;
+                       case 514:
+                               ai = new AreaIdentifier(value);
+                               logger.trace("Parsed area identifier {}", ai);
+                               break;
+                       case 515:
+                               if (value.length == 6) {
+                                       routerId = new ISISRouterIdentifier(new ISOSystemIdentifier(ByteArray.subByte(value, 0, 6)));
+                               } else if (value.length == 7) {
+                                       if (value[6] == 0) {
+                                               logger.warn("PSN octet is 0. Ignoring System ID.");
+                                               routerId = new ISISRouterIdentifier(new ISOSystemIdentifier(ByteArray.subByte(value, 0, 6)));
+                                               break;
+                                       } else
+                                               routerId = new ISISLANIdentifier(new ISOSystemIdentifier(ByteArray.subByte(value, 0, 6)), value[6]);
+                               } else if (value.length == 4) {
+                                       routerId = new OSPFRouterIdentifier(ByteArray.subByte(value, 0, 4));
+                               } else if (value.length == 8) {
+                                       final byte[] o = ByteArray.subByte(value, 0, 4); // FIXME: OSPFv3 vs OSPFv2
+                                       final OSPFInterfaceIdentifier a = new OSPFInterfaceIdentifier(ByteArray.subByte(value, 4, 4));
+                                       routerId = new OSPFv3LANIdentifier(new OSPFRouterIdentifier(o), a);
+                               }
+                               logger.trace("Parsed Router Identifier {}", routerId);
+                               break;
+                       default:
+                               throw new BGPParsingException("Node Descriptor not recognized, type: " + type);
+                       }
+                       byteOffset += length;
+               }
+               logger.debug("Finished parsing Node descriptors.");
+               return new NodeIdentifier(asnumber, bgpId, ai, routerId);
+       }
+
+       private static PrefixIdentifier<?> parsePrefixDescriptors(final NodeIdentifier localDescriptor, final byte[] bytes)
+                       throws BGPParsingException {
+               int byteOffset = 0;
+               TopologyIdentifier topologyId = null;
+               OSPFRouteType routeType = null;
+               Prefix<?> prefix = null;
+               while (byteOffset != bytes.length) {
+                       final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+                       byteOffset += TYPE_LENGTH;
+                       final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+                       byteOffset += LENGTH_SIZE;
+                       final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
+                       logger.trace("Parsing Prefix Descriptor: {}", Arrays.toString(value));
+                       switch (type) {
+                       case 263:
+                               topologyId = new TopologyIdentifier(ByteArray.bytesToLong(value) & 0x3fff);
+                               logger.trace("Parsed Topology Identifier: {}", topologyId);
+                               break;
+                       case 264:
+                               final int rt = ByteArray.bytesToInt(value);
+                               routeType = parseRouteType(rt);
+                               logger.trace("Parser RouteType: {}", routeType);
+                               break;
+                       case 265:
+                               final int prefixLength = UnsignedBytes.toInt(value[0]);
+                               final int size = prefixLength / 8 + ((prefixLength % 8 == 0) ? 0 : 1);
+                               if (size != value.length - 1) {
+                                       logger.debug("Expected length {}, actual length {}.", size, value.length - 1);
+                                       throw new BGPParsingException("Illegal length of IP reachability TLV: " + (value.length - 1));
+                               }
+                               prefix = IPv6.FAMILY.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength);
+                               logger.trace("Parsed IP reachability info: {}", prefix);
+                               break;
+                       default:
+                               throw new BGPParsingException("Prefix Descriptor not recognized, type: " + type);
+                       }
+                       byteOffset += length;
+               }
+               logger.debug("Finished parsing Prefix descriptors.");
+               if (routeType != null) {
+                       if (prefix instanceof IPv4Prefix) {
+                               return new OSPFPrefixIdentifier<IPv4Address>(localDescriptor, (IPv4Prefix) prefix, routeType);
+                       } else {
+                               return new OSPFPrefixIdentifier<IPv6Address>(localDescriptor, (IPv6Prefix) prefix, routeType);
+                       }
+               }
+               return (prefix instanceof IPv4Prefix) ? new IPv4PrefixIdentifier(localDescriptor, (IPv4Prefix) prefix)
+                               : new IPv6PrefixIdentifier(localDescriptor, (IPv6Prefix) prefix);
+       }
+
+       /**
+        * Parse Link Attributes.
+        * 
+        * @param descriptors
+        * @param bytes
+        * @return
+        * @throws BGPParsingException
+        */
+       public static NetworkLinkImpl parseLinkAttributes(final LinkIdentifier linkId, final Map<Integer, ByteList> attributes)
+                       throws BGPParsingException {
+
+               final Set<SharedRiskLinkGroup> sharedRiskLinkGroups = Sets.newHashSet();
+               final Set<MPLSProtocol> enabledMPLSProtocols = Sets.newHashSet();
+               final NetworkLinkImpl link = new NetworkLinkImpl(linkId);
+
+               // FIXME: we should put these somewhere
+               final Set<RouterIdentifier> localIds = Sets.newHashSet();
+               final Set<RouterIdentifier> remoteIds = Sets.newHashSet();
+
+               String name = null;
+               for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
+                       logger.debug("Link attribute TLV {}", entry.getKey());
+
+                       for (final byte[] value : entry.getValue().getBytes()) {
+
+                               switch (entry.getKey()) {
+                               case 1028:
+                                       final IPv4RouterIdentifier lipv4 = new IPv4RouterIdentifier(new IPv4Address(value));
+                                       localIds.add(lipv4);
+                                       logger.trace("Parsed IPv4 Router-ID of local node: {}", lipv4);
+                                       break;
+                               case 1029:
+                                       final IPv6RouterIdentifier lipv6 = new IPv6RouterIdentifier(new IPv6Address(value));
+                                       localIds.add(lipv6);
+                                       logger.trace("Parsed IPv6 Router-ID of local node: {}", lipv6);
+                                       break;
+                               case 1030:
+                                       final IPv4RouterIdentifier ripv4 = new IPv4RouterIdentifier(new IPv4Address(value));
+                                       remoteIds.add(ripv4);
+                                       logger.trace("Parsed IPv4 Router-ID of remote node: {}", ripv4);
+                                       break;
+                               case 1031:
+                                       final IPv6RouterIdentifier ripv6 = new IPv6RouterIdentifier(new IPv6Address(value));
+                                       remoteIds.add(ripv6);
+                                       logger.trace("Parsed IPv6 Router-ID of remote node: {}", ripv6);
+                                       break;
+                               case 1088:
+                                       link.setAdministrativeGroup(new AdministrativeGroup(ByteArray.bytesToLong(value)));
+                                       logger.trace("Parsed Administrative Group {}", link.currentState().getAdministrativeGroup());
+                                       break;
+                               case 1089:
+                                       link.setMaximumBandwidth(new Bandwidth(ByteArray.bytesToFloat(value)));
+                                       logger.trace("Parsed Max Bandwidth {}", link.currentState().getMaximumBandwidth());
+                                       break;
+                               case 1090:
+                                       link.setMaximumReservableBandwidth(new Bandwidth(ByteArray.bytesToFloat(value)));
+                                       logger.trace("Parsed Max Reservable Bandwidth {}", link.currentState().getMaximumReservableBandwidth());
+                                       break;
+                               case 1091:
+                                       int index = 0;
+                                       final Bandwidth[] unreservedBandwidth = new Bandwidth[8];
+                                       for (int i = 0; i < 8; i++) {
+                                               unreservedBandwidth[i] = new Bandwidth(ByteArray.bytesToFloat(ByteArray.subByte(value, index, 4)));
+                                               index += 4;
+                                       }
+                                       link.setUnreservedBandwidth(unreservedBandwidth);
+                                       logger.trace("Parsed Unreserved Bandwidth {}", Arrays.toString(link.currentState().getUnreservedBandwidth()));
+                                       break;
+                               case 1092:
+                                       link.setMetric(TEMetric.class, new TEMetric(ByteArray.bytesToInt(value)));
+                                       logger.trace("Parsed Metric {}", link.currentState().getMetric(TEMetric.class));
+                                       break;
+                               case 1093:
+                                       link.setProtectionType(parseLinkProtectionType(UnsignedBytes.toInt(value[0])));
+                                       logger.trace("Parsed Link Protection Type {}", link.currentState().getProtectionType());
+                                       break;
+                               case 1094:
+                                       final boolean[] bits = ByteArray.parseBits(value[0]);
+                                       if (bits[0] == true) {
+                                               enabledMPLSProtocols.add(MPLSProtocol.LDP);
+                                       }
+                                       if (bits[1] == true) {
+                                               enabledMPLSProtocols.add(MPLSProtocol.RSVPTE);
+                                       }
+                                       logger.trace("Parsed MPLS Protocols: {}", Arrays.toString(enabledMPLSProtocols.toArray()));
+                                       break;
+                               case 1095:
+                                       link.setDefaultMetric(new IGPMetric(ByteArray.bytesToLong(value)));
+                                       logger.trace("Parsed Metric {}", link.currentState().getDefaultMetric());
+                                       break;
+                               case 1096:
+                                       int i = 0;
+                                       while (i != value.length) {
+                                               sharedRiskLinkGroups.add(new SharedRiskLinkGroup(ByteArray.bytesToLong(ByteArray.subByte(value, i, 4))));
+                                               i += 4;
+                                       }
+                                       logger.trace("Parsed Shared Risk Link Groups {}", Arrays.toString(sharedRiskLinkGroups.toArray()));
+                                       break;
+                               case 1097:
+                                       final byte[] opaque = value;
+                                       logger.trace("Parsed Opaque value : {}", Arrays.toString(opaque));
+                                       break;
+                               case 1098:
+                                       name = new String(value, Charsets.US_ASCII);
+                                       logger.trace("Parsed Link Name : ", name);
+                                       break;
+                               default:
+                                       throw new BGPParsingException("Link Attribute not recognized, type: " + entry.getKey());
+                               }
+                       }
+               }
+               link.setEnabledMPLSProtocols(enabledMPLSProtocols);
+               link.setSharedRiskLinkGroups(sharedRiskLinkGroups);
+               link.currentState().withSymbolicName(name);
+               logger.debug("Finished parsing Link Attributes.");
+               return link;
+       }
+
+       /**
+        * Parse Node Attributes.
+        * 
+        * @param descriptors
+        * @param bytes
+        * @return
+        * @throws BGPParsingException
+        */
+       public static NetworkNodeImpl parseNodeAttributes(final NodeIdentifier nodeId, final Map<Integer, ByteList> attributes)
+                       throws BGPParsingException {
+               final Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership = Maps.newHashMap();
+               final Set<ISISAreaIdentifier> areaMembership = Sets.newHashSet();
+               final NetworkNodeImpl node = new NetworkNodeImpl(nodeId);
+               final Set<RouterIdentifier> ids = Sets.newHashSet();
+               for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
+                       logger.debug("Node attribute TLV {}", entry.getKey());
+                       for (final byte[] value : entry.getValue().getBytes()) {
+                               switch (entry.getKey()) {
+                               case 263:
+                                       final boolean[] bits = ByteArray.parseBits(value[0]);
+                                       final TopologyNodeInformation topNodeInfo = new TopologyNodeInformation(bits[1], bits[0]);
+                                       final TopologyIdentifier topId = new TopologyIdentifier(ByteArray.bytesToLong(value) & 0x3fff);
+                                       topologyMembership.put(topId, topNodeInfo);
+                                       logger.trace("Parsed Topology Identifier: {} and Topology Node Information: {}", topId, topNodeInfo);
+                                       break;
+                               case 1024:
+                                       final boolean[] flags = ByteArray.parseBits(value[0]);
+                                       node.setExternal(flags[2]);
+                                       node.setAreaBorderRouter(flags[3]);
+                                       logger.trace("Parsed External bit {}, area border router {}.", flags[2], flags[3]);
+                                       break;
+                               case 1025:
+                                       logger.debug("Ignoring opaque value: {}.", Arrays.toString(value));
+                                       break;
+                               case 1026:
+                                       node.setDynamicHostname(new String(value, Charsets.US_ASCII));
+                                       logger.trace("Parsed Node Name {}", node.currentState().getDynamicHostname());
+                                       break;
+                               case 1027:
+                                       final ISISAreaIdentifier ai = new ISISAreaIdentifier(value);
+                                       areaMembership.add(ai);
+                                       logger.trace("Parsed AreaIdentifier {}", ai);
+                                       break;
+                               case 1028:
+                                       final IPv4RouterIdentifier ip4 = new IPv4RouterIdentifier(new IPv4Address(value));
+                                       ids.add(ip4);
+                                       logger.trace("Parsed IPv4 Router Identifier {}", ip4);
+                                       break;
+                               case 1029:
+                                       final IPv6RouterIdentifier ip6 = new IPv6RouterIdentifier(new IPv6Address(value));
+                                       ids.add(ip6);
+                                       logger.trace("Parsed IPv6 Router Identifier {}", ip6);
+                                       break;
+                               default:
+                                       throw new BGPParsingException("Node Attribute not recognized, type: " + entry.getKey());
+                               }
+                       }
+               }
+
+               node.setAreaMembership(areaMembership);
+               node.setAlternativeIdentifiers(ids);
+               node.setTopologyMembership(topologyMembership);
+               logger.debug("Finished parsing Node Attributes.");
+               return node;
+       }
+
+       public static NetworkPrefixState parsePrefixAttributes(final SourceProtocol src, final NetworkObjectState nos,
+                       final Map<Integer, ByteList> attributes) throws BGPParsingException {
+
+               boolean upDownBit = false;
+               final SortedSet<RouteTag> routeTags = Sets.newTreeSet();
+               final SortedSet<ExtendedRouteTag> exRouteTags = Sets.newTreeSet();
+               Metric<?> metric = null;
+               IPv4Address fwdAddress4 = null;
+               IPv6Address fwdAddress6 = null;
+               for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
+                       logger.debug("Prefix attribute TLV {}", entry.getKey());
+                       for (final byte[] value : entry.getValue().getBytes()) {
+                               switch (entry.getKey()) {
+                               case 1152:
+                                       final boolean[] flags = ByteArray.parseBits(value[0]);
+                                       upDownBit = flags[2];
+                                       logger.trace("Parsed IGP flag (up/down bit) : {}", upDownBit);
+                                       break;
+                               case 1153:
+                                       int offset = 0;
+                                       while (offset != value.length) {
+                                               final RouteTag routeTag = new RouteTag(ByteArray.subByte(value, offset, 4));
+                                               routeTags.add(routeTag);
+                                               logger.trace("Parsed Route Tag: {}", routeTag);
+                                               offset += 4;
+                                       }
+                                       break;
+                               case 1154:
+                                       offset = 0;
+                                       while (offset != value.length) {
+                                               final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(value);
+                                               exRouteTags.add(exRouteTag);
+                                               logger.trace("Parsed Extended Route Tag: {}", exRouteTag);
+                                               offset += 4;
+                                       }
+                                       break;
+                               case 1155:
+                                       metric = new IGPMetric(ByteArray.bytesToLong(value));
+                                       logger.trace("Parsed Metric: {}", metric);
+                                       break;
+                               case 1156:
+                                       switch (value.length) {
+                                       case 4:
+                                               fwdAddress4 = new IPv4Address(value);
+                                               logger.trace("Parsed FWD Address: {}", fwdAddress4);
+                                               break;
+                                       case 16:
+                                               fwdAddress6 = new IPv6Address(value);
+                                               logger.trace("Parsed FWD Address: {}", fwdAddress6);
+                                               break;
+                                       default:
+                                               logger.debug("Ignoring unsupported forwarding address length {}", value.length);
+                                       }
+
+                                       break;
+                               case 1157:
+                                       final byte[] opaque = value;
+                                       logger.trace("Parsed Opaque value: {}", Arrays.toString(opaque));
+                                       break;
+                               default:
+                                       throw new BGPParsingException("Prefix Attribute not recognized, type: " + entry.getKey());
+                               }
+                       }
+               }
+
+               logger.debug("Finished parsing Prefix Attributes.");
+
+               final NetworkPrefixState nps = new NetworkPrefixState(nos, routeTags, metric);
+               switch (src) {
+               case ISISLevel1:
+               case ISISLevel2:
+                       return new ISISNetworkPrefixState(nps, exRouteTags, upDownBit);
+               case OSPF:
+                       if (fwdAddress4 != null)
+                               return new OSPFNetworkPrefixState<IPv4Address>(nps, fwdAddress4);
+                       if (fwdAddress6 != null)
+                               return new OSPFNetworkPrefixState<IPv6Address>(nps, fwdAddress6);
+                       logger.debug("OSPF-sourced has no forwarding address");
+                       return nps;
+               default:
+                       return nps;
+               }
+       }
+
+       /**
+        * Parse Link Protection Type from int to enum
+        * 
+        * @param type int parsed from byte array
+        * @return enum LinkProtectionType
+        * @throws BGPParsingException if the type is unrecognized
+        */
+       private static LinkProtectionType parseLinkProtectionType(final int type) throws BGPParsingException {
+               switch (type) {
+               case 1:
+                       return LinkProtectionType.EXTRA_TRAFFIC;
+               case 2:
+                       return LinkProtectionType.UNPROTECTED;
+               case 4:
+                       return LinkProtectionType.SHARED;
+               case 8:
+                       return LinkProtectionType.DEDICATED_ONE_TO_ONE;
+               case 16:
+                       return LinkProtectionType.DEDICATED_ONE_PLUS_ONE;
+               default:
+                       throw new BGPParsingException("Link Protection Type not recognized: " + type);
+               }
+       }
+
+       /**
+        * Parse NLRI Type from int to enum
+        * 
+        * @param type int parsed from byte array
+        * @return enum NlriType
+        * @throws BGPParsingException if the type is unrecognized
+        */
+       private static NlriType parseNLRItype(final int type) throws BGPParsingException {
+               switch (type) {
+               case 1:
+                       return NlriType.NodeNLRI;
+               case 2:
+                       return NlriType.LinkNLRI;
+               case 3:
+                       return NlriType.IPv4Prefixes;
+               case 4:
+                       return NlriType.IPv6Prefixes;
+               default:
+                       throw new BGPParsingException("NLRI Type not recognized: " + type);
+               }
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachParser.java
new file mode 100644 (file)
index 0000000..e49e5ce
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl.message.update;
+
+import java.util.Set;
+
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+import org.opendaylight.protocol.bgp.concepts.NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.IPv4MP;
+import org.opendaylight.protocol.bgp.parser.impl.IPv6MP;
+import org.opendaylight.protocol.bgp.parser.impl.MPReach;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.Prefix;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for MP_REACH or MP_UNREACH fields.
+ */
+public class MPReachParser {
+
+       private static final int ADDRESS_FAMILY_IDENTIFIER_SIZE = 2;
+
+       private static final int SUBSEQUENT_ADDRESS_FAMILY_IDENTIFIER_SIZE = 1;
+
+       private static final int NEXT_HOP_LENGTH_SIZE = 1;
+
+       private static final int RESERVED_SIZE = 1;
+
+       public static final int LS_AFI = 16388;
+
+       public static final int LS_SAFI = 71;
+
+       private MPReachParser() {
+
+       }
+
+       static MPReach<?> parseMPUnreach(final byte[] bytes) throws BGPParsingException {
+               int byteOffset = 0;
+               final BGPAddressFamily afi = parseAfi(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, ADDRESS_FAMILY_IDENTIFIER_SIZE)));
+               byteOffset += ADDRESS_FAMILY_IDENTIFIER_SIZE;
+               final BGPSubsequentAddressFamily safi = parseSafi(UnsignedBytes.toInt(bytes[byteOffset]));
+               byteOffset += SUBSEQUENT_ADDRESS_FAMILY_IDENTIFIER_SIZE;
+               return chooseUnreachParser(afi, safi, ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset));
+       }
+
+       static MPReach<?> parseMPReach(final byte[] bytes) throws BGPParsingException {
+               int byteOffset = 0;
+               final BGPAddressFamily afi = parseAfi(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, ADDRESS_FAMILY_IDENTIFIER_SIZE)));
+               byteOffset += ADDRESS_FAMILY_IDENTIFIER_SIZE;
+               final BGPSubsequentAddressFamily safi = parseSafi(UnsignedBytes.toInt(bytes[byteOffset]));
+               byteOffset += SUBSEQUENT_ADDRESS_FAMILY_IDENTIFIER_SIZE;
+               final int nextHopLength = UnsignedBytes.toInt(bytes[byteOffset]);
+               byteOffset += NEXT_HOP_LENGTH_SIZE;
+               final NextHop<?> nextHop = parseNextHop(ByteArray.subByte(bytes, byteOffset, nextHopLength));
+               byteOffset += nextHopLength + RESERVED_SIZE;
+               return chooseReachParser(afi, safi, nextHop, ByteArray.subByte(bytes, byteOffset, bytes.length - (byteOffset)));
+       }
+
+       public static BGPSubsequentAddressFamily parseSafi(final int type) throws BGPParsingException {
+               switch (type) {
+               case 1:
+                       return BGPSubsequentAddressFamily.Unicast;
+               case LS_SAFI:
+                       return BGPSubsequentAddressFamily.Linkstate;
+               case 128:
+                       return BGPSubsequentAddressFamily.MPLSLabeledVPN;
+               default:
+                       throw new BGPParsingException("Subsequent Address Family Identifier: '" + type + "' not supported.");
+               }
+       }
+
+       public static BGPAddressFamily parseAfi(final int type) throws BGPParsingException {
+               switch (type) {
+               case 1:
+                       return BGPAddressFamily.IPv4;
+               case 2:
+                       return BGPAddressFamily.IPv6;
+               case LS_AFI:
+                       return BGPAddressFamily.LinkState;
+               default:
+                       throw new BGPParsingException("Address Family Identifier: '" + type + "' not supported.");
+               }
+       }
+
+       private static MPReach<?> chooseUnreachParser(final BGPAddressFamily afi, final BGPSubsequentAddressFamily safi, final byte[] bytes)
+                       throws BGPParsingException {
+               switch (afi) {
+               case IPv4:
+                       final Set<Prefix<IPv4Address>> nlri4 = IPv4.FAMILY.prefixListForBytes(bytes);
+                       return new IPv4MP(false, null, nlri4);
+               case IPv6:
+                       final Set<Prefix<IPv6Address>> nlri6 = IPv6.FAMILY.prefixListForBytes(bytes);
+                       return new IPv6MP(false, null, nlri6);
+               case LinkState:
+                       return LinkStateParser.parseLSNlri(false, safi, null, bytes);
+               default:
+                       return null;
+               }
+       }
+
+       private static MPReach<?> chooseReachParser(final BGPAddressFamily afi, final BGPSubsequentAddressFamily safi,
+                       final NextHop<?> nextHop, final byte[] bytes) throws BGPParsingException {
+               switch (afi) {
+               case IPv4:
+                       final Set<Prefix<IPv4Address>> nlri4 = IPv4.FAMILY.prefixListForBytes(bytes);
+                       return new IPv4MP(true, (IPv4NextHop) nextHop, nlri4);
+               case IPv6:
+                       final Set<Prefix<IPv6Address>> nlri6 = IPv6.FAMILY.prefixListForBytes(bytes);
+                       return new IPv6MP(true, (IPv6NextHop) nextHop, nlri6);
+               case LinkState:
+                       return LinkStateParser.parseLSNlri(true, safi, nextHop, bytes);
+               default:
+                       return null;
+               }
+       }
+
+       private static NextHop<?> parseNextHop(final byte[] bytes) throws BGPParsingException {
+               final NextHop<?> addr;
+               switch (bytes.length) {
+               case 4:
+                       addr = new IPv4NextHop(IPv4.FAMILY.addressForBytes(bytes));
+                       break;
+               case 16:
+                       addr = new IPv6NextHop(IPv6.FAMILY.addressForBytes(bytes));
+                       break;
+               case 32:
+                       addr = new IPv6NextHop(IPv6.FAMILY.addressForBytes(ByteArray.subByte(bytes, 0, 16)), IPv6.FAMILY.addressForBytes(ByteArray.subByte(bytes, 16, 16)));
+                       break;
+               default:
+                       throw new BGPParsingException("Cannot parse NEXT_HOP attribute. Wrong bytes length: " + bytes.length);
+               }
+               return addr;
+       }
+}
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/PathAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/PathAttributeParser.java
new file mode 100644 (file)
index 0000000..dd47f81
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl.message.update;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.BGPAggregator;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.ClusterIdentifier;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.concepts.NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.BGPAggregatorImpl;
+import org.opendaylight.protocol.bgp.parser.impl.ByteList;
+import org.opendaylight.protocol.bgp.parser.impl.MPReach;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute.TypeCode;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.AsPathSegmentParser.SegmentType;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * 
+ * Parser for different Path Attributes. Each attributes has its own method for parsing.
+ * 
+ */
+public class PathAttributeParser {
+
+       private static final int FLAGS_LENGTH = 1;
+
+       private static final int TYPE_LENGTH = 1;
+
+       private PathAttributeParser() {
+
+       }
+
+       /**
+        * Parse path attribute header (the same for all path attributes) and set type, length and value fields.
+        * 
+        * @param bytes byte array to be parsed.
+        * @return generic Path Attribute
+        * @throws BGPParsingException
+        * @throws BGPDocumentedException
+        */
+       public static PathAttribute parseAttribute(final byte[] bytes) throws BGPDocumentedException, BGPParsingException {
+               if (bytes == null || bytes.length == 0)
+                       throw new BGPParsingException("Insufficient length of byte array: " + bytes.length);
+               final boolean[] bits = ByteArray.parseBits(bytes[0]);
+               final PathAttribute attribute = new PathAttribute(bits[0], bits[1], bits[2], bits[3]);
+
+               final int attrLength = (attribute.getAttrLengthSize() == 1) ? UnsignedBytes.toInt(bytes[2])
+                               : ByteArray.bytesToInt(ByteArray.subByte(bytes, 2, 2));
+               attribute.setType(TypeCode.parseType(UnsignedBytes.toInt(bytes[1])));
+
+               if (attribute.getType() == null && !attribute.isOptional())
+                       throw new BGPDocumentedException("Well known attribute not recognized.", BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED);
+
+               attribute.setLength(attrLength);
+               attribute.setValue(chooseParser(attribute.getType(),
+                               ByteArray.subByte(bytes, FLAGS_LENGTH + TYPE_LENGTH + attribute.getAttrLengthSize(), attrLength)));
+               return attribute;
+       }
+
+       /**
+        * Choose corresponding parser to the typecode, that was already parsed.
+        * 
+        * @param type typecode of the path attribute
+        * @param bytes byte array to be parsed
+        * @return Object, because there are various Path Attributes and there is no superclass or interface common for all
+        *         of them.
+        * @throws BGPDocumentedException
+        * @throws BGPParsingException
+        */
+       private static Object chooseParser(final TypeCode type, final byte[] bytes) throws BGPDocumentedException, BGPParsingException {
+               switch (type) {
+               case ORIGIN:
+                       return parseOrigin(bytes);
+               case AS_PATH:
+                       return parseAsPath(bytes);
+               case NEXT_HOP:
+                       return parseNextHop(bytes);
+               case MULTI_EXIT_DISC:
+                       return parseMultiExitDisc(bytes);
+               case LOCAL_PREF:
+                       return parseLocalPref(bytes);
+               case ATOMIC_AGGREGATE:
+                       return null;
+               case AGGREGATOR:
+                       return parseAggregator(bytes);
+               case COMMUNITIES:
+                       return parseCommunities(bytes);
+               case ORIGINATOR_ID:
+                       return parseOriginatorId(bytes);
+               case CLUSTER_LIST:
+                       return parseClusterList(bytes);
+               case MP_REACH_NLRI:
+                       return parseMPReach(bytes);
+               case MP_UNREACH_NLRI:
+                       return parseMPUnreach(bytes);
+               case EXTENDED_COMMUNITIES:
+                       return parseExtendedCommunities(bytes);
+               case LINK_STATE:
+                       return parseLinkState(bytes);
+                       /**
+                        * Recognize, but ignore.
+                        */
+               case AS4_AGGREGATOR:
+                       /**
+                        * Recognize, but ignore.
+                        */
+               case AS4_PATH:
+                       return null;
+               }
+               return null;
+       }
+
+       /**
+        * Parses ORIGIN from bytes.
+        * 
+        * @param bytes byte array to be parsed
+        * @return BGPOrigin enum
+        * @throws BGPParsingException if the Origin value is unknown
+        * @throws BGPDocumentedException
+        */
+       private static BGPOrigin parseOrigin(final byte[] bytes) throws BGPDocumentedException {
+               final int value = UnsignedBytes.toInt(bytes[0]);
+               BGPOrigin origin;
+               switch (value) {
+               case 0:
+                       origin = BGPOrigin.IGP;
+                       break;
+               case 1:
+                       origin = BGPOrigin.EGP;
+                       break;
+               case 2:
+                       origin = BGPOrigin.INCOMPLETE;
+                       break;
+               default:
+                       throw new BGPDocumentedException("Unknown Origin type.", BGPError.ORIGIN_ATTR_NOT_VALID, new byte[] { (byte) 0x01, (byte) 0x01,
+                                       bytes[0] });
+               }
+               return origin;
+       }
+
+       /**
+        * Parses AS_PATH from bytes.
+        * 
+        * @param bytes byte array to be parsed
+        * @return new ASPath object
+        * @throws BGPDocumentedException if there is no AS_SEQUENCE present (mandatory)
+        * @throws BGPParsingException
+        */
+       private static ASPath parseAsPath(final byte[] bytes) throws BGPDocumentedException, BGPParsingException {
+               int byteOffset = 0;
+               List<ASNumber> list = null;
+               Set<ASNumber> set = null;
+               while (byteOffset < bytes.length) {
+                       final int type = UnsignedBytes.toInt(bytes[byteOffset]);
+                       final SegmentType segmentType = AsPathSegmentParser.parseType(type);
+                       if (segmentType == null)
+                               throw new BGPParsingException("AS Path segment type unknown : " + type);
+                       byteOffset += AsPathSegmentParser.TYPE_LENGTH;
+
+                       final int count = UnsignedBytes.toInt(bytes[byteOffset]);
+                       byteOffset += AsPathSegmentParser.LENGTH_SIZE;
+
+                       if (segmentType == SegmentType.AS_SEQUENCE) {
+                               list = (List<ASNumber>) AsPathSegmentParser.parseAsPathSegment(segmentType, count,
+                                               ByteArray.subByte(bytes, byteOffset, count * AsPathSegmentParser.AS_NUMBER_LENGTH));
+                       } else {
+                               set = (Set<ASNumber>) AsPathSegmentParser.parseAsPathSegment(segmentType, count,
+                                               ByteArray.subByte(bytes, byteOffset, count * AsPathSegmentParser.AS_NUMBER_LENGTH));
+                       }
+                       byteOffset += count * AsPathSegmentParser.AS_NUMBER_LENGTH;
+               }
+
+               if (list == null && bytes.length != 0)
+                       throw new BGPDocumentedException("AS_SEQUENCE must be present in AS_PATH attribute.", BGPError.AS_PATH_MALFORMED);
+               return (set != null) ? new ASPath(list, set) : (list == null) ? ASPath.EMPTY : new ASPath(list);
+       }
+
+       /**
+        * Parse NEXT_HOP from bytes
+        * 
+        * @param bytes byte array to be parsed
+        * @return new NextHop object, it's always IPv4 (basic BGP-4)
+        */
+       private static NextHop<IPv4Address> parseNextHop(final byte[] bytes) {
+               return new IPv4NextHop(new IPv4Address(bytes));
+       }
+
+       /**
+        * Parse MULTI_EXIT_DISC (integer) from bytes
+        * 
+        * @param bytes byte array to be parsed
+        * @return integer representing MULTI_EXIT_DISC path attribute
+        */
+       private static int parseMultiExitDisc(final byte[] bytes) {
+               return ByteArray.bytesToInt(bytes);
+       }
+
+       /**
+        * Parse LOCAL_PREF (integer) from bytes
+        * 
+        * @param bytes byte array to be parsed
+        * @return integer representing LOCAL_PREF path attribute
+        */
+       private static int parseLocalPref(final byte[] bytes) {
+               return ByteArray.bytesToInt(bytes);
+       }
+
+       /**
+        * Parse AGGREGATOR from bytes
+        * 
+        * @param bytes byte array to be parsed
+        * @return new BGPAggregator object
+        */
+       private static BGPAggregator parseAggregator(final byte[] bytes) {
+               final ASNumber asNumber = new ASNumber(ByteArray.bytesToLong(ByteArray.subByte(bytes, 0, AsPathSegmentParser.AS_NUMBER_LENGTH)));
+               final IPv4Address address = new IPv4Address(ByteArray.subByte(bytes, AsPathSegmentParser.AS_NUMBER_LENGTH, 4));
+               return new BGPAggregatorImpl<IPv4Address>(asNumber, address);
+       }
+
+       /**
+        * Parse MP_REACH_NLRI from bytes
+        * 
+        * @param bytes byte array to be parsed
+        * @return new specific MPReach object with reachable flag set to true
+        * @throws BGPDocumentedException
+        */
+       private static MPReach<?> parseMPReach(final byte[] bytes) throws BGPDocumentedException {
+               try {
+                       return MPReachParser.parseMPReach(bytes);
+               } catch (final BGPParsingException e) {
+                       throw new BGPDocumentedException("Could not parse MP_REACH_NLRI: " + e.getMessage(), BGPError.OPT_ATTR_ERROR);
+               }
+       }
+
+       /**
+        * Parse MP_UNREACH_NLRI from bytes
+        * 
+        * @param bytes byte array to be parsed
+        * @return new specific MPReach object with reachable flag set to false
+        * @throws BGPDocumentedException
+        */
+       private static MPReach<?> parseMPUnreach(final byte[] bytes) throws BGPDocumentedException {
+               try {
+                       return MPReachParser.parseMPUnreach(bytes);
+               } catch (final BGPParsingException e) {
+                       throw new BGPDocumentedException("Could not parse MP_UNREACH_NLRI: " + e.getMessage(), BGPError.OPT_ATTR_ERROR);
+               }
+       }
+
+       /**
+        * Parse set of EXTENDED_COMMUNITIES from bytes
+        * 
+        * @param bytes byte array to be parsed
+        * @return new specific Extended Community object
+        * @throws BGPDocumentedException l
+        */
+       private static Set<ExtendedCommunity> parseExtendedCommunities(final byte[] bytes) throws BGPDocumentedException {
+               final Set<ExtendedCommunity> set = Sets.newHashSet();
+               int i = 0;
+               while (i < bytes.length) {
+                       set.add(CommunitiesParser.parseExtendedCommunity(ByteArray.subByte(bytes, i, CommunitiesParser.EXTENDED_COMMUNITY_LENGTH)));
+                       i += CommunitiesParser.EXTENDED_COMMUNITY_LENGTH;
+               }
+               return set;
+       }
+
+       /**
+        * Parse set of COMMUNITIES from bytes
+        * 
+        * @param bytes byte array to be parsed
+        * @return new specific Community object
+        * @throws BGPDocumentedException
+        */
+       private static Set<Community> parseCommunities(final byte[] bytes) throws BGPDocumentedException {
+               final Set<Community> set = Sets.newHashSet();
+               int i = 0;
+               while (i < bytes.length) {
+                       set.add(CommunitiesParser.parseCommunity(ByteArray.subByte(bytes, i, CommunitiesParser.COMMUNITY_LENGTH)));
+                       i += CommunitiesParser.COMMUNITY_LENGTH;
+               }
+               return set;
+       }
+
+       /**
+        * Parse list of Cluster Identifiers.
+        * 
+        * @param bytes byte array to be parsed
+        * @return new List of Cluster Identifiers
+        */
+       private static List<ClusterIdentifier> parseClusterList(final byte[] bytes) {
+               final List<ClusterIdentifier> list = Lists.newArrayList();
+               int i = 0;
+               while (i < bytes.length) {
+                       list.add(new ClusterIdentifier(ByteArray.subByte(bytes, i, ClusterIdentifier.SIZE)));
+                       i += ClusterIdentifier.SIZE;
+               }
+               return list;
+       }
+
+       /**
+        * Parses ORIGINATOR_ID, which is BGP Identifier, which is IP address of the speaker.
+        * 
+        * @param bytes byte array to be parsed
+        * @return IP address of the speaker
+        */
+       private static NetworkAddress<?> parseOriginatorId(final byte[] bytes) {
+               if (bytes.length != 4)
+                       throw new IllegalArgumentException("Length of byte array for ORIGINATOR_ID should be 4, but is " + bytes.length);
+               return new IPv4Address(bytes);
+       }
+
+       /**
+        * Parse LINK_STATE from bytes
+        * 
+        * @param bytes byte array to be parsed
+        * @return Map, where the key is the type of a tlv and the value is the value of the tlv
+        */
+       private static Map<Integer, ByteList> parseLinkState(final byte[] bytes) {
+               return LinkStateParser.parseLinkState(bytes);
+       }
+}
diff --git a/bgp/parser-impl/src/site/apt/index.apt.vm b/bgp/parser-impl/src/site/apt/index.apt.vm
new file mode 100644 (file)
index 0000000..240ca24
--- /dev/null
@@ -0,0 +1,6 @@
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
diff --git a/bgp/parser-impl/src/site/site.xml b/bgp/parser-impl/src/site/site.xml
new file mode 100644 (file)
index 0000000..e468b3b
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+  <body>
+    <head>${project.artifactId}</head>
+    <links>
+      <item name="${project.artifactId}" href="index.html"/>
+    </links>
+
+    <menu ref="parent"/>
+
+    <menu ref="reports"/>
+
+    
+  </body>
+</project>
+
diff --git a/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BGPParserTest.java b/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BGPParserTest.java
new file mode 100644 (file)
index 0000000..fd73900
--- /dev/null
@@ -0,0 +1,1151 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPAggregator;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+import org.opendaylight.protocol.bgp.concepts.Inet4SpecificExtendedCommunity;
+import org.opendaylight.protocol.bgp.parser.BGPLink;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPNode;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPRoute;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateEvent;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
+import org.opendaylight.protocol.bgp.parser.impl.BGPAggregatorImpl;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.parser.impl.BGPUpdateMessageImpl;
+import org.opendaylight.protocol.bgp.parser.impl.IPv4MP;
+import org.opendaylight.protocol.bgp.parser.impl.IPv6MP;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute.TypeCode;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPLinkImpl;
+import org.opendaylight.protocol.bgp.util.BGPNodeImpl;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.util.DefaultingTypesafeContainer;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.bgp.linkstate.AreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.DomainIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv4InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkAnchor;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifierFactory;
+import org.opendaylight.protocol.bgp.linkstate.OSPFInterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFRouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFv3LANIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+public class BGPParserTest {
+
+       /**
+        * Used by other tests as well
+        */
+       static final List<byte[]> inputBytes = new ArrayList<byte[]>();
+
+       private static int COUNTER = 17;
+
+       private static int MAX_SIZE = 300;
+
+       @BeforeClass
+       public static void setUp() throws Exception {
+
+               for (int i = 1; i <= COUNTER; i++) {
+                       final String name = "/up" + i + ".bin";
+                       final InputStream is = BGPParserTest.class.getResourceAsStream(name);
+                       if (is == null)
+                               throw new IOException("Failed to get resource " + name);
+
+                       final ByteArrayOutputStream bis = new ByteArrayOutputStream();
+                       final byte[] data = new byte[MAX_SIZE];
+                       int nRead = 0;
+                       while ((nRead = is.read(data, 0, data.length)) != -1) {
+                               bis.write(data, 0, nRead);
+                       }
+                       bis.flush();
+
+                       inputBytes.add(bis.toByteArray());
+               }
+       }
+
+       @Test
+       public void testResource() {
+               assertNotNull(inputBytes);
+       }
+
+       /*
+        * Tests IPv4 NEXT_HOP, ATOMIC_AGGREGATE, COMMUNITY, NLRI
+        * 
+        * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+        * 00 54 <- length (84) - including header
+        * 02 <- message type
+        * 00 00 <- withdrawn routes length
+        * 00 31 <- total path attribute length (49)
+        * 40 <- attribute flags
+        * 01 <- attribute type code (origin)
+        * 01 <- attribute length
+        * 00 <- Origin value (IGP)
+        * 40 <- attribute flags
+        * 02 <- attribute type code (as path)
+        * 06 <- attribute length
+        * 02 <- AS_SEQUENCE
+        * 01 <- path segment count
+        * 00 00 fd ea <- path segment value (65002)
+        * 40 <- attribute flags
+        * 03 <- attribute type code (Next Hop)
+        * 04 <- attribute length
+        * 10 00 00 02 <- value (10.0.0.2)
+        * 80 <- attribute flags
+        * 04 <- attribute type code (multi exit disc)
+        * 04 <- attribute length
+        * 00 00 00 00 <- value
+        * 64 <- attribute flags
+        * 06 <- attribute type code (atomic aggregate)
+        * 00 <- attribute length
+        * 64 <- attribute flags
+        * 08 <- attribute type code (community)
+        * 10 <- attribute length FF FF FF
+        * 01 <- value (NO_EXPORT)
+        * FF FF FF 02 <- value (NO_ADVERTISE)
+        * FF FF FF 03 <- value (NO_EXPORT_SUBCONFED)
+        * FF FF FF 10 <- unknown Community
+        * 
+        * //NLRI
+        * 18 ac 11 02 <- IPv4 Prefix (172.17.2.0 / 24)
+        * 18 ac 11 01 <- IPv4 Prefix (172.17.1.0 / 24)
+        * 18 ac 11 00 <- IPv4 Prefix (172.17.0.0 / 24)
+        */
+       @Test
+       public void testGetUpdateMessage1() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(0), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(0), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+               assertTrue(ret instanceof BGPUpdateMessage);
+               final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+               // check fields
+
+               assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+               // attributes
+
+               final ASPath asPath = new ASPath(Lists.newArrayList(new ASNumber(65002)));
+
+               final IPv4NextHop nextHop = IPv4NextHop.forString("10.0.0.2");
+
+               final Set<Community> comms = Sets.newHashSet(Community.NO_EXPORT, Community.NO_ADVERTISE, Community.NO_EXPORT_SUBCONFED,
+                               new Community(new ASNumber(0xFFFF), 0xFF10));
+
+               // check path attributes
+
+               // final PathAttribute originAttr = new PathAttribute(TypeCode.ORIGIN, false,
+               // true, false, false, BGPOrigin.IGP);
+               // assertEquals(originAttr, attrs.get(0));
+               //
+               // final PathAttribute asPathAttr = new PathAttribute(TypeCode.AS_PATH, false,
+               // true, false, false, asPath);
+               // assertEquals(asPathAttr, attrs.get(1));
+               //
+               // final PathAttribute nextHopAttr = new PathAttribute(TypeCode.NEXT_HOP, false,
+               // true, false, false, nextHop);
+               // assertEquals(nextHopAttr, attrs.get(2));
+               //
+               // final PathAttribute multiExitDisc = new PathAttribute(
+               // TypeCode.MULTI_EXIT_DISC, true, false, false, false, 0);
+               // assertEquals(multiExitDisc, attrs.get(3));
+               //
+               // final PathAttribute atomic = new PathAttribute(TypeCode.ATOMIC_AGGREGATE, false,
+               // true, true, false, null);
+               // assertEquals(atomic, attrs.get(4));
+               //
+               // final PathAttribute comm = new PathAttribute(TypeCode.COMMUNITIES, false,
+               // true, true, false, comms);
+               // assertEquals(comm, attrs.get(5));
+
+               // check nlri
+
+               // final Set<IPv4Prefix> nlri = Sets.newHashSet(pref1, pref2, pref3);
+               // assertEquals(nlri, ret.getBgpUpdateMessageBuilder().getNlri());
+
+               final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.IGP, null);
+               final NetworkRouteState<IPv4Address> routeState = new NetworkRouteState<>(new NetworkObjectState(asPath, comms, Collections.<ExtendedCommunity> emptySet()), nextHop);
+
+               // check API message
+
+               final Set<BGPObject> addedObjects = Sets.newHashSet();
+
+               final BGPRoute<IPv4Address> route1 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("172.17.2.0/24"), state, routeState);
+
+               addedObjects.add(route1);
+
+               final BGPRoute<IPv4Address> route2 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("172.17.1.0/24"), state, routeState);
+
+               addedObjects.add(route2);
+
+               final BGPRoute<IPv4Address> route3 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("172.17.0.0/24"), state, routeState);
+
+               addedObjects.add(route3);
+
+               final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(addedObjects, Collections.<Identifier> emptySet());
+
+               assertEquals(expectedMessage, message);
+
+       }
+
+       /*
+        * Tests IPv6 NEXT_HOP, NLRI, ORIGIN.IGP, MULTI_EXIT_DISC, ORIGINATOR-ID, CLUSTER_LIST.
+        * 
+        * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+        * 00 80 <- length (128) - including header
+        * 02 <- message type
+        * 00 00 <- withdrawn routes length
+        * 00 69 <- total path attribute length (105)
+        * 40 <- attribute flags
+        * 01 <- attribute type code (origin)
+        * 01 <- attribute length
+        * 00 <- Origin value (IGP)
+        * 40 <- attribute flags
+        * 02 <- attribute type code (as path)
+        * 06 <- attribute length
+        * 02 <- AS_SEQUENCE
+        * 01 <- path segment count
+        * 00 00 fd e9 <- path segment value (65001)
+        * 80 <- attribute flags
+        * 04 <- attribute type code (multi exit disc)
+        * 04 <- attribute length
+        * 00 00 00 00 <- value
+        * 80 <- attribute flags
+        * 09 <- attribute type code (originator id)
+        * 04 <- attribute length
+        * 7f 00 00 01 <- value (localhost ip)
+        * 80 <- attribute flags
+        * 0a <- attribute type code (cluster list)
+        * 08 <- attribute length
+        * 01 02 03 04 <- value
+        * 05 06 07 08 <- value
+        * 80 <- attribute flags
+        * 0e <- attribute type code (mp reach nlri)
+        * 40 <- attribute length
+        * 00 02 <- AFI (Ipv6)
+        * 01 <- SAFI (Unicast)
+        * 20 <- length of next hop
+        * 20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 01 <- global
+        * fe 80 00 00 00 00 00 00 c0 01 0b ff fe 7e 00 <- link local
+        * 00 <- reserved
+        * 
+        * //NLRI
+        * 40 20 01 0d b8 00 01 00 02 <- IPv6 Prefix (2001:db8:1:2:: / 64)
+        * 40 20 01 0d b8 00 01 00 01 <- IPv6 Prefix (2001:db8:1:1:: / 64)
+        * 40 20 01 0d b8 00 01 00 00 <- IPv6 Prefix (2001:db8:1:: / 64)
+        * 
+        */
+       @Test
+       public void testGetUpdateMessage2() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(1), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(1), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+               assertTrue(ret instanceof BGPUpdateMessage);
+               final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+               // check fields
+
+               assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+               // attributes
+
+               final ASPath asPath = new ASPath(Lists.newArrayList(new ASNumber(65001)));
+
+               final IPv6NextHop nextHop = IPv6NextHop.forString("2001:db8::1", "fe80::c001:bff:fe7e:0");
+
+               // final List<ClusterIdentifier> clusters = Lists.newArrayList(
+               // new ClusterIdentifier(new byte[] { 1, 2, 3, 4}),
+               // new ClusterIdentifier(new byte[] { 5, 6, 7, 8}));
+
+               // check path attributes
+
+               // final PathAttribute originAttr = new PathAttribute(TypeCode.ORIGIN, false,
+               // true, false, false, BGPOrigin.IGP);
+               // assertEquals(originAttr, attrs.get(0));
+               //
+               // final PathAttribute asPathAttr = new PathAttribute(TypeCode.AS_PATH, false,
+               // true, false, false, asPath);
+               // assertEquals(asPathAttr, attrs.get(1));
+               //
+               // final PathAttribute multiExitDisc = new PathAttribute(
+               // TypeCode.MULTI_EXIT_DISC, true, false, false, false, 0);
+               // assertEquals(multiExitDisc, attrs.get(2));
+               //
+               // final PathAttribute originatorAttr = new PathAttribute(
+               // TypeCode.ORIGINATOR_ID, true, false, false, false, IPv4.FAMILY.addressForString("127.0.0.1"));
+               // assertEquals(originatorAttr, attrs.get(3));
+               //
+               // final PathAttribute clusterAttr = new PathAttribute(
+               // TypeCode.CLUSTER_LIST, true, false, false, false, clusters);
+               // assertEquals(clusterAttr, attrs.get(4));
+
+               final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.IGP, null);
+               final NetworkRouteState<IPv6Address> routeState = new NetworkRouteState<>(new NetworkObjectState(asPath, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet()), nextHop);
+
+               // check API message
+
+               final Set<BGPObject> addedObjects = Sets.newHashSet();
+
+               final BGPRoute<IPv6Address> route1 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("2001:db8:1:2::/64"), state, routeState);
+
+               addedObjects.add(route1);
+
+               final BGPRoute<IPv6Address> route2 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("2001:db8:1:1::/64"), state, routeState);
+
+               addedObjects.add(route2);
+
+               final BGPRoute<IPv6Address> route3 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("2001:db8:1::/64"), state, routeState);
+
+               addedObjects.add(route3);
+
+               final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(addedObjects, Collections.<Identifier> emptySet());
+
+               assertEquals(expectedMessage, message);
+       }
+
+       /*
+        * Tests more AS Numbers in AS_PATH, AGGREGATOR, ORIGIN.INCOMPLETE
+        * 
+        * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+        * 00 4b <- length (75) - including header
+        * 02 <- message type
+        * 00 00 <- withdrawn routes length
+        * 00 30 <- total path attribute length (48)
+        * 40 <- attribute flags
+        * 01 <- attribute type code (origin)
+        * 01 <- attribute length
+        * 02 <- Origin value (Incomplete)
+        * 40 <- attribute flags
+        * 02 <- attribute type code (as path)
+        * 10 <- attribute length
+        * 02 <- AS_SEQUENCE
+        * 01 <- path segment count
+        * 00 00 00 1e <- path segment value (30)
+        * 01 <- AS_SET
+        * 02 <- path segment count
+        * 00 00 00 0a <- path segment value (10)
+        * 00 00 00 14 <- path segment value (20)
+        * 40 <- attribute flags
+        * 03 <- attribute type (Next hop)
+        * 04 <- attribute length
+        * 0a 00 00 09 <- value (10.0.0.9)
+        * 80 <- attribute flags
+        * 04 <- attribute type code (multi exit disc)
+        * 04 <- attribute length
+        * 00 00 00 00 <- value
+        * c0 <- attribute flags
+        * 07 <- attribute type (Aggregator)
+        * 08 <- attribute length
+        * 00 00 00 1e <- value (AS number = 30)
+        * 0a 00 00 09 <- value (IP address = 10.0.0.9)
+        * 
+        * //NLRI
+        * 15 ac 10 00 <- IPv4 Prefix (172.16.0.0 / 21)
+        */
+       @Test
+       public void testGetUpdateMessage3() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(2), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(2), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+               assertTrue(ret instanceof BGPUpdateMessage);
+               final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+               // check fields
+               assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+               // attributes
+
+               final ASPath asPath = new ASPath(Lists.newArrayList(new ASNumber(30)), Sets.newHashSet(new ASNumber(10), new ASNumber(20)));
+
+               final BGPAggregator aggregator = new BGPAggregatorImpl<IPv4Address>(new ASNumber(30), IPv4.FAMILY.addressForString("10.0.0.9"));
+               final IPv4NextHop nextHop = IPv4NextHop.forString("10.0.0.9");
+
+               final IPv4Prefix pref1 = IPv4.FAMILY.prefixForString("172.16.0.0/21");
+
+               // check path attributes
+
+               // final PathAttribute originAttr = new PathAttribute(TypeCode.ORIGIN, false,
+               // true, false, false, BGPOrigin.INCOMPLETE);
+               // assertEquals(originAttr, attrs.get(0));
+               //
+               // final PathAttribute asPathAttr = new PathAttribute(TypeCode.AS_PATH, false,
+               // true, false, false, asPath);
+               // assertEquals(asPathAttr, attrs.get(1));
+               //
+               // final PathAttribute nextHopAttr = new PathAttribute(TypeCode.NEXT_HOP, false,
+               // true, false, false, nextHop);
+               // assertEquals(nextHopAttr, attrs.get(2));
+               //
+               // final PathAttribute multiExitDisc = new PathAttribute(
+               // TypeCode.MULTI_EXIT_DISC, true, false, false, false, 0);
+               // assertEquals(multiExitDisc, attrs.get(3));
+               //
+               // final PathAttribute agg = new PathAttribute(TypeCode.AGGREGATOR, true, true,
+               // false, false, aggregator);
+               // assertEquals(agg, attrs.get(4));
+               //
+               // // check nlri
+               //
+               // final Set<IPv4Prefix> nlri = Sets.newHashSet(pref1);
+               // assertEquals(nlri, ret.getBgpUpdateMessageBuilder().getNlri());
+
+               final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.INCOMPLETE, aggregator);
+               final NetworkRouteState<IPv4Address> routeState = new NetworkRouteState<>(new NetworkObjectState(asPath, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet()), nextHop);
+
+               // check API message
+
+               final Set<BGPObject> addedObjects = Sets.newHashSet();
+
+               final BGPRoute<IPv4Address> route1 = new BGPIPv4RouteImpl(pref1, state, routeState);
+
+               addedObjects.add(route1);
+
+               final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(addedObjects, Collections.<Identifier> emptySet());
+
+               assertEquals(expectedMessage, message);
+
+       }
+
+       /*
+        * Tests empty AS_PATH, ORIGIN.EGP, LOCAL_PREF, EXTENDED_COMMUNITIES (Ipv4 Addr specific)
+        * 
+        * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+        * 00 4A <- length (73) - including header
+        * 02 <- message type
+        * 00 00 <- withdrawn routes length
+        * 00 27 <- total path attribute length (39)
+        * 40 <- attribute flags
+        * 01 <- attribute type code (Origin)
+        * 01 <- attribute length
+        * 01 <- Origin value (EGP)
+        * 40 <- attribute flags
+        * 02 <- attribute type code (As path)
+        * 00 <- attribute length
+        * 40 <- attribute flags
+        * 03 <- attribute type (Next hop)
+        * 04 <- attribute length
+        * 03 03 03 03 <- value (3.3.3.3)
+        * 80 <- attribute flags
+        * 04 <- attribute type code (Multi exit disc)
+        * 04 <- attribute length
+        * 00 00 00 00 <- value
+        * 40 <- attribute flags
+        * 05 <- attribute type (Local Pref)
+        * 04 <- attribute length
+        * 00 00 00 64 <- value (100)
+        * 80 <- attribute flags
+        * 10 <- attribute type (extended community)
+        * 08 <- attribute length
+        * 01 04 <- value (type - Ipv4 Address Specific Extended Community)
+        * c0 a8 01 00 <- value (global adm. 198.162.1.0)
+        * 12 34 <- value (local adm. 4660)
+        * 
+        * //NLRI
+        * 18 0a 1e 03 <- IPv4 Prefix (10.30.3.0 / 24)
+        * 18 0a 1e 02 <- IPv4 Prefix (10.30.2.0 / 24)
+        * 18 0a 1e 01 <- IPv4 Prefix (10.30.1.0 / 24)
+        */
+       @Test
+       public void testGetUpdateMessage4() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(3), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(3), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+               assertTrue(ret instanceof BGPUpdateMessage);
+               final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+               // check fields
+
+               assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+               // attributes
+
+               final IPv4NextHop nextHop = IPv4NextHop.forString("3.3.3.3");
+
+               final Set<ExtendedCommunity> comms = Sets.newHashSet((ExtendedCommunity) new Inet4SpecificExtendedCommunity(false, 4, IPv4.FAMILY.addressForString("192.168.1.0"), new byte[] {
+                               0x12, 0x34 }));
+
+               // check path attributes
+
+               // final PathAttribute originAttr = new PathAttribute(TypeCode.ORIGIN, false,
+               // true, false, false, BGPOrigin.EGP);
+               // assertEquals(originAttr, attrs.get(0));
+               //
+               // final PathAttribute asPathAttr = new PathAttribute(TypeCode.AS_PATH, false,
+               // true, false, false, asPath);
+               // assertEquals(asPathAttr, attrs.get(1));
+               //
+               // final PathAttribute nextHopAttr = new PathAttribute(TypeCode.NEXT_HOP, false,
+               // true, false, false, nextHop);
+               // assertEquals(nextHopAttr, attrs.get(2));
+               //
+               // final PathAttribute multiExitDisc = new PathAttribute(
+               // TypeCode.MULTI_EXIT_DISC, true, false, false, false, 0);
+               // assertEquals(multiExitDisc, attrs.get(3));
+               //
+               // final PathAttribute localPref = new PathAttribute(TypeCode.LOCAL_PREF, false,
+               // true, false, false, 100);
+               // assertEquals(localPref, attrs.get(4));
+
+               // check nlri
+               //
+               // final Set<IPv4Prefix> nlri = Sets.newHashSet(pref1, pref2, pref3);
+               // assertEquals(nlri, ret.getBgpUpdateMessageBuilder().getNlri());
+
+               final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.EGP, null);
+               final NetworkRouteState<IPv4Address> routeState = new NetworkRouteState<>(new NetworkObjectState(ASPath.EMPTY, Collections.<Community> emptySet(), comms), nextHop);
+
+               // check API message
+
+               final Set<BGPObject> addedObjects = Sets.newHashSet();
+
+               final BGPRoute<IPv4Address> route1 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("10.30.3.0/24"), state, routeState);
+
+               addedObjects.add(route1);
+
+               final BGPRoute<IPv4Address> route2 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("10.30.2.0/24"), state, routeState);
+
+               addedObjects.add(route2);
+
+               final BGPRoute<IPv4Address> route3 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("10.30.1.0/24"), state, routeState);
+
+               addedObjects.add(route3);
+
+               final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(addedObjects, Collections.<Identifier> emptySet());
+
+               assertEquals(expectedMessage, message);
+       }
+
+       /*
+        * Tests withdrawn routes.
+        * 
+        * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+        * 00 1c <- length (28) - including header
+        * 02 <- message type
+        * 00 05 <- withdrawn routes length (5)
+        * 1e ac 10 00 04 <- route (172.16.0.4)
+        * 00 00 <- total path attribute length
+        */
+       @Test
+       public void testGetUpdateMessage5() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(4), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(4), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+               assertTrue(ret instanceof BGPUpdateMessage);
+               final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+               // attributes
+
+               final IPv4Prefix pref1 = IPv4.FAMILY.prefixForString("172.16.0.4/30");
+
+               // check API message
+
+               final BGPUpdateEvent expectedMessage = new BGPUpdateMessageImpl(Collections.<BGPObject> emptySet(), Sets.newHashSet((Identifier) pref1));
+
+               assertEquals(expectedMessage, message);
+       }
+
+       /*
+        * Test EOR for IPv4.
+        * 
+        * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+        * 00 17 <- length (23) - including header
+        * 02 <- message type
+        * 00 00 <- withdrawn routes length
+        * 00 00 <- total path attribute length
+        */
+       @Test
+       public void testEORIpv4() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(5), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(5), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+               assertTrue(ret instanceof BGPUpdateSynchronized);
+               final BGPUpdateSynchronized message = (BGPUpdateSynchronized) ret;
+
+               final BGPUpdateSynchronized expectedMessage = new BGPUpdateSynchronized() {
+
+                       private static final long serialVersionUID = -5128220996581568885L;
+
+                       @Override
+                       public BGPTableType getTableType() {
+                               return new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+                       }
+               };
+               assertEquals(expectedMessage.getTableType(), message.getTableType());
+       }
+
+       /*
+        * End of Rib for Ipv6 consists of empty MP_UNREACH_NLRI, with AFI 2 and SAFI 1
+        * 
+        * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+        * 00 1d <- length (29) - including header
+        * 02 <- message type
+        * 00 00 <- withdrawn routes length
+        * 00 06 <- total path attribute length
+        * 80 <- attribute flags
+        * 0f <- attribute type (15 - MP_UNREACH_NLRI)
+        * 03 <- attribute length
+        * 00 02 <- value (AFI 2: IPv6)
+        * 01 <- value (SAFI 1)
+        */
+       @Test
+       public void testEORIpv6() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(6), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(6), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+               assertTrue(ret instanceof BGPUpdateSynchronized);
+               final BGPUpdateSynchronized message = (BGPUpdateSynchronized) ret;
+
+               // check fields
+
+               final BGPUpdateSynchronized expectedMessage = new BGPUpdateSynchronized() {
+
+                       private static final long serialVersionUID = -4811827044855997014L;
+
+                       @Override
+                       public BGPTableType getTableType() {
+                               return new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.Unicast);
+                       }
+               };
+               assertEquals(expectedMessage.getTableType(), message.getTableType());
+       }
+
+       /*
+        * End of Rib for LS consists of empty MP_UNREACH_NLRI, with AFI 16388 and SAFI 71
+        * 
+        * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+        * 00 1d <- length (29) - including header
+        * 02 <- message type
+        * 00 00 <- withdrawn routes length
+        * 00 06 <- total path attribute length
+        * 80 <- attribute flags
+        * 0f <- attribute type (15 - MP_UNREACH_NLRI)
+        * 03 <- attribute length
+        * 40 04 <- value (AFI 16388: LS)
+        * 47 <- value (SAFI 71)
+        */
+       @Test
+       public void testEORLS() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(7), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(7), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+               assertTrue(ret instanceof BGPUpdateSynchronized);
+               final BGPUpdateSynchronized message = (BGPUpdateSynchronized) ret;
+
+               // check fields
+
+               final BGPUpdateSynchronized expectedMessage = new BGPUpdateSynchronized() {
+
+                       private static final long serialVersionUID = 3677704232769769042L;
+
+                       @Override
+                       public BGPTableType getTableType() {
+                               return new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Unicast);
+                       }
+               };
+
+               assertEquals(expectedMessage.getTableType(), message.getTableType());
+       }
+
+       /*
+        *  Tests BGP Link Ipv4
+        * 
+               00 00 <- withdrawn routes length
+               01 48 <- total path attribute length (328)
+               90 <- attribute flags
+               0e <- attribute type code (MP reach)
+               01 2c <- attribute extended length (300)
+               40 04 <- AFI (16388 - Linkstate)
+               47 <- SAFI (71 - Linkstate)
+               04 <- next hop length
+               19 19 19 01 <- nexthop (25.25.25.1)
+               00 <- reserved
+
+               00 02 <- NLRI type (2 - linkNLRI)
+               00 5d <- NLRI length (93)
+               03 <- ProtocolID - OSPF
+               00 00 00 00 00 00 00 01 <- identifier
+
+               01 00 <- local node descriptor type (256)
+               00 24 <- length (36)
+               02 00 <- node descriptor type (member AS - 512)
+               00 04 <- length
+               00 00 00 64 <- value (100)
+               02 01 <- node descriptor type (bgpId - 513)
+               00 04 <- length
+               19 19 19 01 <- bgpId (25.25.25.1)
+               02 02 <- node descriptor type (areaId - 514)
+               00 04 <- length
+               00 00 00 00 <- value
+               02 03 <- node descriptor type (routeId - 515)
+               00 08 <- length
+               03 03 03 04 0b 0b 0b 03 <- OSPF Router Id
+
+               01 01 <- remote node descriptor type (257)
+               00 20 <- length (32)
+               02 00 <- node descriptor type (member AS - 512)
+               00 04 <- length
+               00 00 00 64 <- value (100)
+               02 01 <- node descriptor type (bgpId - 513)
+               00 04 <- length
+               19 19 19 01 <- bgpId (25.25.25.1)
+               02 02 <- node descriptor type (areaId - 514)
+               00 04 <- length
+               00 00 00 00 <- value
+               02 03 <- node descriptor type (routeId - 515)
+               00 04 <- length
+               03 03 03 04 <- OSPF Router Id
+
+               01 03 <- link descriptor type (IPv4 interface address - 259)
+               00 04 <- length (4)
+               0b 0b 0b 03 <- value (11.11.11.3)
+
+               00 02 <- NLRI type (2 - linkNLRI)
+               00 5d <- NLRI length (93)
+               03 <- ProtocolID - OSPF
+               00 00 00 00 00 00 00 01 <- identifier
+
+               01 00 <- local node descriptor type (256)
+               00 24 <- length (36)
+               02 00 <- node descriptor type (member AS - 512)
+               00 04 <- length
+               00 00 00 64 <- value (100)
+               02 01 <- node descriptor type (bgpId - 513)
+               00 04 <- length
+               19 19 19 01 <- bgpId (25.25.25.1)
+               02 02 <- node descriptor type (areaId - 514)
+               00 04 <- length
+               00 00 00 00 <- value
+               02 03 <- node descriptor type (routeId - 515)
+               00 08 <- length
+               03 03 03 04 0b 0b 0b 03 <- OSPF Router Id
+
+               01 01 <- remote node descriptor type (257)
+               00 20 <- length (32)
+               02 00 <- node descriptor type (member AS - 512)
+               00 04 <- length
+               00 00 00 64 <- value (100)
+               02 01 <- node descriptor type (bgpId - 513)
+               00 04 <- length
+               19 19 19 01 <- bgpId (25.25.25.1)
+               02 02 <- node descriptor type (areaId - 514)
+               00 04 <- length
+               00 00 00 00 <- value
+               02 03 <- node descriptor type (routeId - 515)
+               00 04 <- length
+               01 01 01 02 <- OSPF Router Id
+
+               01 03 <- link descriptor type (IPv4 interface address - 259)
+               00 04 <- length
+               0b 0b 0b 01 <- value (11.11.11.1)
+
+               00 02 <- NLRI type (2 - linkNLRI)
+               00 5d <- NLRI length (93)
+               03 <- ProtocolID - OSPF
+               00 00 00 00 00 00 00 01 <- identifier
+
+               01 00 <- local node descriptor type (256)
+               00 20 <- length (32)
+               02 00 <- node descriptor type (member AS - 512)
+               00 04 <- length
+               00 00 00 64 <- value (100)
+               02 01 <- node descriptor type (bgpId - 513)
+               00 04 <- length
+               19 19 19 01 <- bgpId (25.25.25.1)
+               02 02 <- node descriptor type (areaId - 514)
+               00 04 <- length
+               00 00 00 00 <- value
+               02 03 <- node descriptor type (routeId - 515)
+               00 04 <- length
+               01 01 01 02 <- OSPF Router Id
+
+               01 01 <- remote node descriptor type (257)
+               00 24 <- length (36)
+               02 00 <- node descriptor type (member AS - 512)
+               00 04 <- length
+               00 00 00 64 <- value (100)
+               02 01 <- node descriptor type (bgpId - 513)
+               00 04 <- length
+               19 19 19 01 <- bgpId (25.25.25.1)
+               02 02 <- node descriptor type (areaId - 514)
+               00 04 <- length
+               00 00 00 00 <- value
+               02 03 <- node descriptor type (routeId - 515)
+               00 08 <- length
+               03 03 03 04 0b 0b 0b 03 <- OSPF Router Id
+
+               01 03 <- link descriptor type (IPv4 interface address - 259)
+               00 04 <- length
+               0b 0b 0b 01 <- value (11.11.11.1)
+
+               40 <- attribute flags
+               01 <- attribute type (Origin)
+               01 <- attribute length
+               00 <- value (IGP)
+               40 <- attribute flags
+               02 <- attribute type (AS Path)
+               00 <- length
+               40 <- attribute flags
+               05 <- attribute type (local pref)
+               04 <- length
+               00 00 00 64 <- value
+               c0 <- attribute flags
+               63 <- attribute type (Link STATE - 99)
+               07 <- length
+               04 47 <- link attribute (1095 - Metric)
+               00 03 <- length
+               00 00 01 <- value
+        */
+       @Test
+       public void testBGPLink() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(8), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(8), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+               assertTrue(ret instanceof BGPUpdateMessage);
+               final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+               // check fields
+
+               assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+               // network object state
+               final NetworkObjectState objState = new NetworkObjectState(ASPath.EMPTY, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+               final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.IGP, null);
+
+               // network link state
+               final DefaultingTypesafeContainer<Metric<?>> container = new DefaultingTypesafeContainer<Metric<?>>();
+               container.setDefaultEntry(new IGPMetric(1));
+               final NetworkLinkState linkState = new NetworkLinkState(objState, container, null, LinkProtectionType.UNPROTECTED, null, null, null);
+
+               final NodeIdentifierFactory f100 = new NodeIdentifierFactory(new ASNumber(100), new DomainIdentifier(new byte[] { 25, 25, 25, 1 }), new AreaIdentifier(new byte[] {
+                               0, 0, 0, 0 }));
+
+               final NodeIdentifier nodeid1 = f100.identifierForRouter(new OSPFv3LANIdentifier(new OSPFRouterIdentifier(new byte[] { 3, 3, 3, 4 }), new OSPFInterfaceIdentifier(new byte[] {
+                               0x0b, 0x0b, 0x0b, 0x03 })));
+               final NodeIdentifier nodeid2 = f100.identifierForRouter(new OSPFRouterIdentifier(new byte[] { 3, 3, 3, 4 }));
+
+               final NodeIdentifier nodeid3 = f100.identifierForRouter(new OSPFRouterIdentifier(new byte[] { 1, 1, 1, 2 }));
+
+               // check API message
+
+               final LinkIdentifier linkId1 = new LinkIdentifier(null, new LinkAnchor(nodeid1, new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForString("11.11.11.3"))), new LinkAnchor(nodeid2, null));
+               final LinkIdentifier linkId2 = new LinkIdentifier(null, new LinkAnchor(nodeid1, new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForString("11.11.11.1"))), new LinkAnchor(nodeid3, null));
+               final LinkIdentifier linkId3 = new LinkIdentifier(null, new LinkAnchor(nodeid3, new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForString("11.11.11.1"))), new LinkAnchor(nodeid1, null));
+
+               final BGPLink link1 = new BGPLinkImpl(state, linkId1, linkState);
+               final BGPLink link2 = new BGPLinkImpl(state, linkId2, linkState);
+               final BGPLink link3 = new BGPLinkImpl(state, linkId3, linkState);
+
+               final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(Sets.newHashSet((BGPObject) link1, (BGPObject) link2,
+                               (BGPObject) link3), Collections.<Identifier> emptySet());
+
+               assertEquals(expectedMessage, message);
+       }
+
+       /*
+        * TEST BGP Node
+        * 
+        *  00 00 <- withdrawn routes length
+               00 b2 <- total path attribute length (178)
+               90 <- attribute flags
+               0e <- attribute type code (MP reach)
+               00 a0 <- attribute extended length (160)
+               40 04 <- AFI (16388 - Linkstate)
+               47 <- SAFI (71 - Linkstate)
+               04 <- next hop length
+               19 19 19 01 - nexthop (25.25.25.1)
+               00 <- reserved
+               00 01 <- NLRI type (1 - nodeNLRI)
+               00 31 <- NLRI length (49)
+               03 <- ProtocolID - OSPF
+               00 00 00 00 00 00 00 01 <- identifier
+       
+               01 00 <- local node descriptor type (256)
+               00 24 <- length (36)
+               02 00 <- node descriptor type (member AS - 512)
+               00 04 <- length
+               00 00 00 64 <- value (100)
+               02 01 <- node descriptor type (bgpId - 513)
+               00 04 <- length
+               19 19 19 01 <- bgpId (25.25.25.1)
+               02 02 <- node descriptor type (areaId - 514)
+               00 04 <- length
+               00 00 00 00 <- value
+               02 03 <- node descriptor type (routeId - 515)
+               00 08 <- length
+               03 03 03 04 0b 0b 0b 03 <- OSPF Router Id
+       
+               00 01 <- NLRI type (1 - nodeNLRI)
+               00 2d <- NLRI length (45)
+               03 <- ProtocolID - OSPF
+               00 00 00 00 00 00 00 01 <- identifier
+       
+               01 00 <- local node descriptor type (256)
+               00 20 <- length (32)
+               02 00 <- node descriptor type (member AS - 512)
+               00 04 <- length
+               00 00 00 64 <- value (100)
+               02 01 <- node descriptor type (bgpId - 513)
+               00 04 <- length
+               19 19 19 01 <- bgpId (25.25.25.1)
+               02 02 <- node descriptor type (areaId - 514)
+               00 04 <- length
+               00 00 00 00 <- value
+               02 03 <- node descriptor type (routeId - 515)
+               00 04 <- length
+               03 03 03 04 <- OSPF Router Id
+       
+               00 01 <- NLRI type (1 - nodeNLRI)
+               00 2d <- NLRI length (45)
+               03 <- ProtocolID - OSPF
+               00 00 00 00 00 00 00 01 <- identifier
+               01 00 <- local node descriptor type (256)
+               00 20 <- length (32)
+               02 00 <- node descriptor type (member AS - 512)
+               00 04 <- length
+               00 00 00 64 <- value (100)
+               02 01 <- node descriptor type (bgpId - 513)
+               00 04 <- length
+               19 19 19 01 <- bgpId (25.25.25.1)
+               02 02 <- node descriptor type (areaId - 514)
+               00 04 <- length
+               00 00 00 00 <- value
+               02 03 <- node descriptor type (routeId - 515)
+               00 04 <- length
+               01 01 01 02  <- OSPF Router Id
+       
+               40 <- attribute flags
+               01 <- attribute type (Origin)
+               01 <- attribute length
+               00 <- value (IGP)
+               40 <- attribute flags
+               02 <- attribute type (AS Path)
+               00 <- length
+               40 <- attribute flags
+               05 <- attribute type (local pref)
+               04 <- length
+               00 00 00 64 <- value
+        */
+       @Test
+       public void testBGPNode() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(9), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(9), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+               assertTrue(ret instanceof BGPUpdateMessage);
+               final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+               // check fields
+
+               assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+               // network object state
+               final NetworkObjectState objState = new NetworkObjectState(ASPath.EMPTY, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+               final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.IGP, null);
+               final NetworkNodeState nstate = new NetworkNodeState(objState, Collections.<TopologyIdentifier, TopologyNodeInformation> emptyMap(), Collections.<ISISAreaIdentifier> emptySet(), false, false, Collections.<RouterIdentifier> emptySet(), null);
+
+               // network link state
+
+               final NodeIdentifierFactory f100 = new NodeIdentifierFactory(new ASNumber(100), new DomainIdentifier(new byte[] { 25, 25, 25, 1 }), new AreaIdentifier(new byte[] {
+                               0, 0, 0, 0 }));
+
+               final NodeIdentifier nodeid1 = f100.identifierForRouter(new OSPFv3LANIdentifier(new OSPFRouterIdentifier(new byte[] { 3, 3, 3, 4 }), new OSPFInterfaceIdentifier(new byte[] {
+                               0x0b, 0x0b, 0x0b, 0x03 })));
+               final NodeIdentifier nodeid2 = f100.identifierForRouter(new OSPFRouterIdentifier(new byte[] { 3, 3, 3, 4 }));
+
+               final NodeIdentifier nodeid3 = f100.identifierForRouter(new OSPFRouterIdentifier(new byte[] { 1, 1, 1, 2 }));
+
+               // check API message
+
+               final BGPNode node1 = new BGPNodeImpl(state, nodeid1, nstate);
+               final BGPNode node2 = new BGPNodeImpl(state, nodeid2, nstate);
+               final BGPNode node3 = new BGPNodeImpl(state, nodeid3, nstate);
+
+               final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(Sets.newHashSet((BGPObject) node1, (BGPObject) node2,
+                               (BGPObject) node3), Collections.<Identifier> emptySet());
+
+               assertEquals(expectedMessage, message);
+       }
+
+       /*
+        * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+        * 00 98 <- length (69) - including header
+        * 01 <- message type
+        * 04 <- BGP version
+        * 00 64 <- My AS Number (AS TRANS in this case)
+        * 00 b4 <- Hold Time
+        * 00 00 00 00 <- BGP Identifier
+        * 28 <- Optional Parameters Length
+        * 02 <- opt. param. type (capabilities)
+        * 06 <- length
+        * 01 <- capability code (MP Extensions for BGP4)
+        * 04 <- length
+        * 00 01 00 01 <- AFI 1, SAFI 1
+        * 02 <- opt. param. type (capabilities)
+        * 06 <- length
+        * 01 <- capability code (MP Extensions for BGP4)
+        * 04 <- length
+        * 00 02 00 01 <- AFI 2, SAFI 1
+        * 02 <- opt. param. type (capabilities)
+        * 06 <- length
+        * 01 <- capability code (MP Extensions for BGP4)
+        * 04 <- length
+        * 40 04 00 47 <- AFI 16388, SAFI 71
+        * 02 <- opt. param. type (capabilities)
+        * 02 <- length
+        * 80 <- capability code (private)
+        * 00 <- length
+        * 02 <- opt. param. type (capabilities)
+        * 02 <- length
+        * 02 <- capability code (Route refresh)
+        * 00 <- length
+        * 02 <- opt. param. type (capabilities)
+        * 06 <- length
+        * 41 <- capability code (AS4 octet support)
+        * 04 <- length
+        * 00 00 00 64 <- AS number
+        */
+       @Test
+       public void testOpenMessage() throws Exception {
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(inputBytes.get(13), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(inputBytes.get(13), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPMessageFactory msgFactory = new BGPMessageFactory();
+               final BGPOpenMessage open = (BGPOpenMessage) msgFactory.parse(body, header);
+               final Set<BGPTableType> types = Sets.newHashSet();
+               for (final BGPParameter param : open.getOptParams()) {
+                       if (param instanceof MultiprotocolCapability) {
+                               types.add(((MultiprotocolCapability) param).getTableType());
+                       }
+               }
+               final Set<BGPTableType> expected = Sets.newHashSet(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast),
+                               new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.Unicast),
+                               new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Linkstate));
+               msgFactory.close();
+               assertEquals(expected, types);
+       }
+
+       @Test
+       public void testHashCodeEquals() throws UnknownHostException {
+               final BGPAggregator agg1 = new BGPAggregatorImpl<IPv4Address>(new ASNumber(6), IPv4.FAMILY.addressForString("10.0.0.9"));
+
+               final BGPAggregator agg2 = new BGPAggregatorImpl<IPv4Address>(new ASNumber(6), IPv4.FAMILY.addressForString("10.0.0.9"));
+
+               assertEquals(agg1, agg2);
+               assertEquals("HashCodes should be equal", agg1.hashCode(), agg2.hashCode());
+               assertEquals("toString should be equal", agg1.toString(), agg2.toString());
+
+               final IPv4MP mp41 = new IPv4MP(false, new IPv4NextHop(IPv4.FAMILY.addressForString("10.0.0.9")), null);
+
+               final IPv4MP mp42 = new IPv4MP(false, new IPv4NextHop(IPv4.FAMILY.addressForString("10.0.0.9")), null);
+
+               assertEquals(mp41, mp42);
+               assertEquals("HashCodes should be equal", mp41.hashCode(), mp42.hashCode());
+               assertEquals("toString should be equal", mp41.toString(), mp42.toString());
+
+               final IPv6MP mp61 = new IPv6MP(false, new IPv6NextHop(IPv6.FAMILY.addressForString("fe80::c001:bff:fe7e:0")), null);
+
+               final IPv6MP mp62 = new IPv6MP(false, new IPv6NextHop(IPv6.FAMILY.addressForString("fe80::c001:bff:fe7e:0")), null);
+
+               assertEquals(mp61, mp62);
+               assertEquals("HashCodes should be equal", mp61.hashCode(), mp62.hashCode());
+               assertEquals("toString should be equal", mp61.toString(), mp62.toString());
+
+               final PathAttribute localPref1 = new PathAttribute(TypeCode.LOCAL_PREF, false, true, false, false, 100);
+
+               final PathAttribute localPref2 = new PathAttribute(TypeCode.LOCAL_PREF, false, true, false, false, 100);
+
+               assertEquals(localPref1, localPref2);
+               assertEquals("HashCodes should be equal", localPref1.hashCode(), localPref2.hashCode());
+               assertEquals("toString should be equal", localPref1.toString(), localPref2.toString());
+       }
+}
diff --git a/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateMessageParserTest.java b/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateMessageParserTest.java
new file mode 100644 (file)
index 0000000..72d6a4e
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPNode;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateEvent;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
+import org.opendaylight.protocol.bgp.util.HexDumpBGPFileParser;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class BGPUpdateMessageParserTest {
+
+       @Test
+       @Ignore
+       public void testNodeParsing() throws Exception {
+               final List<byte[]> result = HexDumpBGPFileParser.parseMessages(new File(this.getClass().getResource("/bgp-update-nodes.txt").getFile()));
+               assertEquals(1, result.size());
+               final BGPMessageHeader header = new BGPMessageHeader();
+               header.fromBytes(ByteArray.subByte(result.get(0), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+               final byte[] body = ByteArray.cutBytes(result.get(0), BGPMessageHeader.COMMON_HEADER_LENGTH);
+               final BGPUpdateEvent event = BGPUpdateMessageParser.parse(body, header.getLength());
+               final BGPUpdateMessage updateMessage = (BGPUpdateMessage) event;
+               final Set<BGPObject> addedObjects = updateMessage.getAddedObjects();
+               assertEquals(14, addedObjects.size());
+               assertEquals(0, updateMessage.getRemovedObjects().size());
+               for (final BGPObject bgpObject : addedObjects) {
+                       assertTrue(bgpObject instanceof BGPNode);
+               }
+       }
+}
diff --git a/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/ComplementaryTest.java b/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/ComplementaryTest.java
new file mode 100644 (file)
index 0000000..6cb71f4
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ASSpecificExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.Inet4SpecificExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.OpaqueExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.RouteOriginCommunity;
+import org.opendaylight.protocol.bgp.concepts.RouteTargetCommunity;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.BGPAggregatorImpl;
+import org.opendaylight.protocol.bgp.parser.impl.BGPLinkMP;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.parser.impl.BGPUpdateMessageImpl;
+import org.opendaylight.protocol.bgp.parser.impl.ByteList;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.CommunitiesParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.MPReachParser;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv4InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISLANIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISRouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkAnchor;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifierFactory;
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+import com.google.common.collect.Sets;
+
+public class ComplementaryTest {
+
+       @Test
+       public void testBGPAggregatorImpl() {
+               final BGPAggregatorImpl<IPv4Address> ipv4 = new BGPAggregatorImpl<IPv4Address>(new ASNumber(5524), IPv4.FAMILY.addressForString("124.55.42.1"));
+               final BGPAggregatorImpl<IPv4Address> ipv4i = new BGPAggregatorImpl<IPv4Address>(new ASNumber(5525), IPv4.FAMILY.addressForString("124.55.42.1"));
+
+               assertNotSame(ipv4.hashCode(), ipv4i.hashCode());
+
+               assertEquals(ipv4, new BGPAggregatorImpl<IPv4Address>(new ASNumber(5524), IPv4.FAMILY.addressForString("124.55.42.1")));
+
+               assertNotSame(ipv4.getASNumber(), ipv4i.getASNumber());
+
+               assertEquals(ipv4.getNetworkAddress(), ipv4i.getNetworkAddress());
+       }
+
+       @Test
+       public void testBGPLinkMP() {
+               final NodeIdentifier localnodeid = new NodeIdentifier(new ASNumber(25600, 0), null, null, new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] {
+                               0x22, 0x22, 0x22, 0x22, 0x22, 0x22 })));
+               final NodeIdentifier remotenodeid = NodeIdentifierFactory.localIdentifier(new ISISLANIdentifier(new ISOSystemIdentifier(new byte[] {
+                               0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }), (short) 1));
+
+               final InterfaceIdentifier ifaceid = new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForString("10.1.1.1"));
+
+               final LinkIdentifier l = new LinkIdentifier(null, new LinkAnchor(localnodeid, ifaceid), new LinkAnchor(remotenodeid, ifaceid));
+
+               final Set<LinkIdentifier> links = Sets.newHashSet(l);
+
+               final BGPLinkMP link = new BGPLinkMP(0, SourceProtocol.Direct, true, links);
+
+               final BGPLinkMP link1 = new BGPLinkMP(0, SourceProtocol.Direct, true, Collections.<LinkIdentifier> emptySet());
+
+               assertNotSame(link.hashCode(), link1.hashCode());
+
+               assertEquals(link, new BGPLinkMP(0, SourceProtocol.Direct, true, links));
+
+               assertEquals(link.hashCode(), (new BGPLinkMP(0, SourceProtocol.Direct, true, links)).hashCode());
+
+               assertNotSame(link.toString(), link1.toString());
+       }
+
+       @Test
+       public void testBGPUpdateMessageImpl() {
+               final BGPUpdateMessageImpl msg = new BGPUpdateMessageImpl(null, null);
+               final BGPUpdateMessageImpl msg1 = new BGPUpdateMessageImpl(null, null);
+
+               assertEquals(msg, msg1);
+
+               assertEquals(msg.hashCode(), msg1.hashCode());
+
+               assertNotNull(msg.toString());
+
+               assertNull(msg.getAddedObjects());
+               assertNull(msg.getRemovedObjects());
+
+               assertNotSame(msg1, null);
+       }
+
+       @Test
+       public void testCommunitiesParser() {
+               ASSpecificExtendedCommunity as = null;
+               try {
+                       as = (ASSpecificExtendedCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 0, 5, 0, 54, 0, 0, 1, 76 });
+               } catch (final BGPDocumentedException e1) {
+                       fail("Not expected exception: " + e1);
+               }
+               assertEquals(as, new ASSpecificExtendedCommunity(false, 5, new ASNumber(54), new byte[] { 0, 0, 1, 76 }));
+
+               try {
+                       as = (ASSpecificExtendedCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 40, 5, 0, 54, 0, 0, 1, 76 });
+               } catch (final BGPDocumentedException e1) {
+                       fail("Not expected exception: " + e1);
+               }
+               assertEquals(as, new ASSpecificExtendedCommunity(true, 5, new ASNumber(54), new byte[] { 0, 0, 1, 76 }));
+
+               RouteTargetCommunity rtc = null;
+               try {
+                       rtc = (RouteTargetCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 1, 2, 0, 35, 4, 2, 8, 7 });
+               } catch (final BGPDocumentedException e1) {
+                       fail("Not expected exception: " + e1);
+               }
+               assertEquals(rtc, new RouteTargetCommunity(new ASNumber(35), new byte[] { 4, 2, 8, 7 }));
+
+               RouteOriginCommunity roc = null;
+               try {
+                       roc = (RouteOriginCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 0, 3, 0, 24, 4, 2, 8, 7 });
+               } catch (final BGPDocumentedException e1) {
+                       fail("Not expected exception: " + e1);
+               }
+               assertEquals(roc, new RouteOriginCommunity(new ASNumber(24), new byte[] { 4, 2, 8, 7 }));
+
+               Inet4SpecificExtendedCommunity sec = null;
+               try {
+                       sec = (Inet4SpecificExtendedCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 41, 6, 12, 51, 2, 5, 21, 45 });
+               } catch (final BGPDocumentedException e1) {
+                       fail("Not expected exception: " + e1);
+               }
+               assertEquals(sec, new Inet4SpecificExtendedCommunity(true, 6, IPv4.FAMILY.addressForString("12.51.2.5"), new byte[] { 21, 45 }));
+
+               OpaqueExtendedCommunity oec = null;
+               try {
+                       oec = (OpaqueExtendedCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 3, 6, 21, 45, 5, 4, 3, 1 });
+               } catch (final BGPDocumentedException e1) {
+                       fail("Not expected exception: " + e1);
+               }
+               assertEquals(oec, new OpaqueExtendedCommunity(false, 6, new byte[] { 21, 45, 5, 4, 3, 1 }));
+
+               try {
+                       oec = (OpaqueExtendedCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 43, 6, 21, 45, 5, 4, 3, 1 });
+               } catch (final BGPDocumentedException e1) {
+                       fail("Not expected exception: " + e1);
+               }
+               assertEquals(oec, new OpaqueExtendedCommunity(true, 6, new byte[] { 21, 45, 5, 4, 3, 1 }));
+
+               try {
+                       CommunitiesParser.parseExtendedCommunity(new byte[] { 11, 11, 21, 45, 5, 4, 3, 1 });
+                       fail("Exception should have occured.");
+               } catch (final BGPDocumentedException e) {
+                       assertEquals("Could not parse Extended Community type: 11", e.getMessage());
+               }
+       }
+
+       @Test
+       public void testMPReachParser() {
+               String msg = "";
+               try {
+                       MPReachParser.parseSafi(5);
+                       fail("Exception shoul have occured.");
+               } catch (final BGPParsingException e) {
+                       msg = e.getMessage();
+               }
+               assertEquals("Subsequent Address Family Identifier: '5' not supported.", msg);
+
+               try {
+                       MPReachParser.parseAfi(6);
+                       fail("Exception should have occured.");
+               } catch (final BGPParsingException e) {
+                       msg = e.getMessage();
+               }
+               assertEquals("Address Family Identifier: '6' not supported.", msg);
+       }
+
+       @Test
+       public void testByteList() {
+               final ByteList b1 = new ByteList();
+               b1.add(new byte[] { 3, 4, 8 });
+               b1.add(new byte[] { 3, 4, 9 });
+
+               final ByteList b2 = new ByteList();
+               b2.add(new byte[] { 3, 4, 8 });
+               b2.add(new byte[] { 3, 4, 9 });
+
+               assertEquals(b1, b2);
+               assertEquals(b1.toString(), b2.toString());
+       }
+
+       @Test
+       public void testMessageParser() throws IOException {
+               final BGPMessageFactory parser = new BGPMessageFactory();
+               String ex = "";
+               try {
+                       parser.put(null);
+               } catch (final IllegalArgumentException e) {
+                       ex = e.getMessage();
+               }
+               parser.close();
+               assertEquals("BGPMessage is mandatory.", ex);
+       }
+}
diff --git a/bgp/parser-impl/src/test/resources/bgp-update-nodes.txt b/bgp/parser-impl/src/test/resources/bgp-update-nodes.txt
new file mode 100644 (file)
index 0000000..2e87cd5
--- /dev/null
@@ -0,0 +1,32 @@
+ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
+01 f2 02 00 00 01 db 90  0e 01 bb 00 1b 01 04 0a
+01 01 0a 00 00 02 00 1b  01 00 00 00 01 00 00 13
+01 02 00 04 00 00 00 64  01 06 00 07 00 00 00 00
+00 01 00 00 02 00 1b 01  00 00 00 01 00 00 13 01
+02 00 04 00 00 00 64 01  06 00 07 00 00 00 00 00
+01 03 00 02 00 1b 01 00  00 00 01 00 00 13 01 02
+00 04 00 00 00 64 01 06  00 07 00 00 00 00 00 02
+00 00 02 00 1b 01 00 00  00 01 00 00 13 01 02 00
+04 00 00 00 64 01 06 00  07 00 00 00 00 00 02 05
+00 02 00 1b 01 00 00 00  01 00 00 13 01 02 00 04
+00 00 00 64 01 06 00 07  00 00 00 00 00 10 00 00
+02 00 1b 01 00 00 00 01  00 00 13 01 02 00 04 00
+00 00 64 01 06 00 07 00  00 00 00 00 10 01 00 02
+00 1b 01 00 00 00 01 00  00 13 01 02 00 04 00 00
+00 64 01 06 00 07 00 00  00 00 00 10 05 00 02 00
+1b 01 00 00 00 01 00 00  13 01 02 00 04 00 00 00
+64 01 06 00 07 00 00 00  00 00 10 07 00 02 00 1b
+01 00 00 00 01 00 00 13  01 02 00 04 00 00 00 64
+01 06 00 07 00 00 00 00  00 30 00 00 02 00 1b 01
+00 00 00 01 00 00 13 01  02 00 04 00 00 00 64 01
+06 00 07 00 00 00 00 00  30 01 00 02 00 1b 01 00
+00 00 01 00 00 13 01 02  00 04 00 00 00 64 01 06
+00 07 00 00 00 00 00 40  00 00 02 00 1b 01 00 00
+00 01 00 00 13 01 02 00  04 00 00 00 64 01 06 00
+07 00 00 00 00 00 40 01  00 02 00 1b 01 00 00 00
+01 00 00 13 01 02 00 04  00 00 00 64 01 06 00 07
+00 00 00 00 00 40 03 00  02 00 1b 01 00 00 00 01
+00 00 13 01 02 00 04 00  00 00 64 01 06 00 07 00
+00 02 05 00 03 00 40 01  01 00 40 02 00 40 05 04
+00 00 00 64 80 0a 04 14  14 14 14 80 09 04 64 64
+64 0a 
\ No newline at end of file
diff --git a/bgp/parser-impl/src/test/resources/up1.bin b/bgp/parser-impl/src/test/resources/up1.bin
new file mode 100644 (file)
index 0000000..aee2226
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up1.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up10.bin b/bgp/parser-impl/src/test/resources/up10.bin
new file mode 100755 (executable)
index 0000000..b0385c2
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up10.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up11.bin b/bgp/parser-impl/src/test/resources/up11.bin
new file mode 100755 (executable)
index 0000000..119172e
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up11.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up12.bin b/bgp/parser-impl/src/test/resources/up12.bin
new file mode 100755 (executable)
index 0000000..f761dca
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up12.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up13.bin b/bgp/parser-impl/src/test/resources/up13.bin
new file mode 100755 (executable)
index 0000000..166b737
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up13.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up14.bin b/bgp/parser-impl/src/test/resources/up14.bin
new file mode 100755 (executable)
index 0000000..a3e666b
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up14.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up15.bin b/bgp/parser-impl/src/test/resources/up15.bin
new file mode 100755 (executable)
index 0000000..24533c3
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up15.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up16.bin b/bgp/parser-impl/src/test/resources/up16.bin
new file mode 100755 (executable)
index 0000000..910dbcc
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up16.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up17.bin b/bgp/parser-impl/src/test/resources/up17.bin
new file mode 100755 (executable)
index 0000000..0eb3f8e
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up17.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up2.bin b/bgp/parser-impl/src/test/resources/up2.bin
new file mode 100644 (file)
index 0000000..c3aba85
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up2.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up3.bin b/bgp/parser-impl/src/test/resources/up3.bin
new file mode 100755 (executable)
index 0000000..f8afa74
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up3.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up4.bin b/bgp/parser-impl/src/test/resources/up4.bin
new file mode 100644 (file)
index 0000000..d82315c
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up4.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up5.bin b/bgp/parser-impl/src/test/resources/up5.bin
new file mode 100644 (file)
index 0000000..f8aa854
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up5.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up6.bin b/bgp/parser-impl/src/test/resources/up6.bin
new file mode 100644 (file)
index 0000000..a15b491
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up6.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up7.bin b/bgp/parser-impl/src/test/resources/up7.bin
new file mode 100755 (executable)
index 0000000..9c32c76
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up7.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up8.bin b/bgp/parser-impl/src/test/resources/up8.bin
new file mode 100755 (executable)
index 0000000..c851127
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up8.bin differ
diff --git a/bgp/parser-impl/src/test/resources/up9.bin b/bgp/parser-impl/src/test/resources/up9.bin
new file mode 100755 (executable)
index 0000000..29b9cb9
Binary files /dev/null and b/bgp/parser-impl/src/test/resources/up9.bin differ
diff --git a/bgp/parser-mock/.gitignore b/bgp/parser-mock/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/bgp/parser-mock/.project b/bgp/parser-mock/.project
new file mode 100644 (file)
index 0000000..46756de
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>bgp-parser-mock</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bgp/parser-mock/pom.xml b/bgp/parser-mock/pom.xml
new file mode 100644 (file)
index 0000000..6afa94a
--- /dev/null
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>bgp-parent</artifactId>
+               <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-parser-mock</artifactId>
+       <description>BGP Parser Mock Implementation</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-parser-api</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-parser-impl</artifactId>
+                       <version>1.0</version>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.bgp.parser.mock
+                                               </Export-Package>
+                                               <Import-Package>
+                                                       org.opendaylight.protocol.bgp.parser,
+                                                       org.opendaylight.protocol.framework,
+                                                       org.opendaylight.protocol.concepts
+                                               </Import-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>BGP-PARSER-MOCK Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/bgp/parser-mock/src/main/java/org/opendaylight/protocol/bgp/parser/mock/BGPMessageParserMock.java b/bgp/parser-mock/src/main/java/org/opendaylight/protocol/bgp/parser/mock/BGPMessageParserMock.java
new file mode 100644 (file)
index 0000000..cbc2b1f
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.mock;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+
+/**
+ * Mock implementation of {@link BGPMessageParser}. It implements the required interface by having two internal maps,
+ * each used in one of the methods. It looks up the key provided to the method and returns whatever value is stored in
+ * the map.
+ */
+public class BGPMessageParserMock implements BGPMessageParser {
+       private final Map<byte[], BGPMessage> messages;
+
+       /**
+        * @param updateMessages Map<byte[], BGPUpdateEvent>
+        */
+       public BGPMessageParserMock(final Map<byte[], BGPMessage> messages) {
+               this.messages = messages;
+       }
+
+       @Override
+       public void close() throws IOException {
+               // nothing
+       }
+
+       @Override
+       public BGPMessage parse(final byte[] bytes, final ProtocolMessageHeader msgHeader) throws DeserializerException, DocumentedException {
+               final BGPMessage ret = this.messages.get(bytes);
+               if (ret == null)
+                       throw new IllegalArgumentException("Undefined message encountered");
+               return ret;
+       }
+
+       @Override
+       public byte[] put(final ProtocolMessage msg) {
+               // nothing
+               return null;
+       }
+}
diff --git a/bgp/parser-mock/src/main/resources/up0.bin b/bgp/parser-mock/src/main/resources/up0.bin
new file mode 100644 (file)
index 0000000..42e1b36
Binary files /dev/null and b/bgp/parser-mock/src/main/resources/up0.bin differ
diff --git a/bgp/parser-mock/src/main/resources/up1.bin b/bgp/parser-mock/src/main/resources/up1.bin
new file mode 100644 (file)
index 0000000..8fa2b21
Binary files /dev/null and b/bgp/parser-mock/src/main/resources/up1.bin differ
diff --git a/bgp/parser-mock/src/main/resources/up10.bin b/bgp/parser-mock/src/main/resources/up10.bin
new file mode 100644 (file)
index 0000000..ecd5f6d
Binary files /dev/null and b/bgp/parser-mock/src/main/resources/up10.bin differ
diff --git a/bgp/parser-mock/src/main/resources/up2.bin b/bgp/parser-mock/src/main/resources/up2.bin
new file mode 100644 (file)
index 0000000..ec30102
--- /dev/null
@@ -0,0 +1,2 @@
+\14\13\12\11\10\ f\ e\r\f\v
+       \b\a\ 6\ 5\ 4\ 3\ 2\ 1
\ No newline at end of file
diff --git a/bgp/parser-mock/src/main/resources/up3.bin b/bgp/parser-mock/src/main/resources/up3.bin
new file mode 100644 (file)
index 0000000..a77521f
Binary files /dev/null and b/bgp/parser-mock/src/main/resources/up3.bin differ
diff --git a/bgp/parser-mock/src/main/resources/up4.bin b/bgp/parser-mock/src/main/resources/up4.bin
new file mode 100644 (file)
index 0000000..30184df
Binary files /dev/null and b/bgp/parser-mock/src/main/resources/up4.bin differ
diff --git a/bgp/parser-mock/src/main/resources/up5.bin b/bgp/parser-mock/src/main/resources/up5.bin
new file mode 100644 (file)
index 0000000..a476c08
Binary files /dev/null and b/bgp/parser-mock/src/main/resources/up5.bin differ
diff --git a/bgp/parser-mock/src/main/resources/up6.bin b/bgp/parser-mock/src/main/resources/up6.bin
new file mode 100644 (file)
index 0000000..8e41240
Binary files /dev/null and b/bgp/parser-mock/src/main/resources/up6.bin differ
diff --git a/bgp/parser-mock/src/main/resources/up7.bin b/bgp/parser-mock/src/main/resources/up7.bin
new file mode 100644 (file)
index 0000000..d00866f
Binary files /dev/null and b/bgp/parser-mock/src/main/resources/up7.bin differ
diff --git a/bgp/parser-mock/src/main/resources/up8.bin b/bgp/parser-mock/src/main/resources/up8.bin
new file mode 100644 (file)
index 0000000..1b1cb4d
Binary files /dev/null and b/bgp/parser-mock/src/main/resources/up8.bin differ
diff --git a/bgp/parser-mock/src/main/resources/up9.bin b/bgp/parser-mock/src/main/resources/up9.bin
new file mode 100644 (file)
index 0000000..523c29b
Binary files /dev/null and b/bgp/parser-mock/src/main/resources/up9.bin differ
diff --git a/bgp/parser-mock/src/site/apt/index.apt.vm b/bgp/parser-mock/src/site/apt/index.apt.vm
new file mode 100644 (file)
index 0000000..240ca24
--- /dev/null
@@ -0,0 +1,6 @@
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
diff --git a/bgp/parser-mock/src/site/site.xml b/bgp/parser-mock/src/site/site.xml
new file mode 100644 (file)
index 0000000..e468b3b
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+  <body>
+    <head>${project.artifactId}</head>
+    <links>
+      <item name="${project.artifactId}" href="index.html"/>
+    </links>
+
+    <menu ref="parent"/>
+
+    <menu ref="reports"/>
+
+    
+  </body>
+</project>
+
diff --git a/bgp/parser-mock/src/test/java/org/opendaylight/protocol/bgp/parser/mock/BGPMessageParserMockTest.java b/bgp/parser-mock/src/test/java/org/opendaylight/protocol/bgp/parser/mock/BGPMessageParserMockTest.java
new file mode 100644 (file)
index 0000000..22e056a
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.mock;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+import org.opendaylight.protocol.bgp.concepts.NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPRoute;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.parser.impl.BGPUpdateMessageImpl;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.mock.BGPMessageParserMock;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class BGPMessageParserMockTest {
+
+       private final byte[][] inputBytes = new byte[11][];
+       private final List<BGPUpdateMessage> messages = new ArrayList<BGPUpdateMessage>();
+
+       @Before
+       public void init() throws Exception {
+               // Creating input bytes and update messages
+               for (int i = 0; i < this.inputBytes.length; i++) {
+                       this.inputBytes[i] = this.fillInputBytes(i);
+                       this.messages.add(this.fillMessages(i));
+               }
+       }
+
+       /**
+        * Test if mock implementation of parser returns correct message
+        * 
+        * @throws DocumentedException
+        * @throws DeserializerException
+        * @throws IOException
+        */
+       @Test
+       public void testGetUpdateMessage() throws DeserializerException, DocumentedException, IOException {
+               final Map<byte[], BGPMessage> updateMap = Maps.newHashMap();
+               for (int i = 0; i < this.inputBytes.length; i++) {
+                       updateMap.put(this.inputBytes[i], this.messages.get(i));
+               }
+
+               final BGPMessageParserMock mockParser = new BGPMessageParserMock(updateMap);
+
+               for (int i = 0; i < this.inputBytes.length; i++) {
+                       assertEquals(this.messages.get(i), mockParser.parse(this.inputBytes[i], null));
+               }
+               assertThat(this.messages.get(3), not(mockParser.parse(this.inputBytes[8], null)));
+
+               mockParser.close();
+       }
+
+       /**
+        * Test if method throws IllegalArgumentException after finding no BGPUpdateMessage associated with given byte[] key
+        * 
+        * @throws DocumentedException
+        * @throws DeserializerException
+        * @throws IOException
+        */
+       @Test(expected = IllegalArgumentException.class)
+       public void testGetUpdateMessageException() throws DeserializerException, DocumentedException, IOException {
+               final Map<byte[], BGPMessage> updateMap = Maps.newHashMap();
+               for (int i = 0; i < this.inputBytes.length; i++) {
+                       updateMap.put(this.inputBytes[i], this.messages.get(i));
+               }
+
+               final BGPMessageParserMock mockParser = new BGPMessageParserMock(updateMap);
+               mockParser.parse(new byte[] { 7, 4, 6 }, new BGPMessageHeader());
+
+               mockParser.close();
+       }
+
+       /**
+        * Helper method to fill inputBytes variable
+        * 
+        * @param fileNumber parameter to distinguish between files from which bytes are read
+        */
+       private byte[] fillInputBytes(final int fileNumber) throws Exception {
+
+               final InputStream is = this.getClass().getResourceAsStream("/up" + fileNumber + ".bin");
+               final ByteArrayOutputStream bis = new ByteArrayOutputStream();
+               final byte[] data = new byte[60];
+               int nRead = 0;
+
+               while ((nRead = is.read(data, 0, data.length)) != -1) {
+                       bis.write(data, 0, nRead);
+               }
+               bis.flush();
+               return bis.toByteArray();
+       }
+
+       /**
+        * Helper method to fill messages variable
+        * 
+        * @param asn this parameter is passed to ASNumber constructor
+        */
+       private BGPUpdateMessage fillMessages(final int asn) throws UnknownHostException {
+
+               final List<ASNumber> asnums = new ArrayList<ASNumber>();
+               asnums.add(new ASNumber(asn));
+               final ASPath asPath = new ASPath(asnums);
+               final NextHop<IPv6Address> nextHop = new IPv6NextHop(new IPv6Address(InetAddress.getByName("2001:db8::1")), new IPv6Address(InetAddress.getByName("fe80::c001:bff:fe7e:0")));
+
+               final Prefix<IPv6Address> pref1 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:1:2::")), 64);
+               final Prefix<IPv6Address> pref2 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:1:1::")), 64);
+               final Prefix<IPv6Address> pref3 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:1::")), 64);
+
+               final Set<BGPObject> addedObjects = new HashSet<BGPObject>();
+
+               final NetworkRouteState<IPv6Address> nstate = new NetworkRouteState<>(new NetworkObjectState(asPath, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet()), nextHop);
+               final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.IGP, null);
+
+               final BGPRoute<IPv6Address> route1 = new BGPIPv6RouteImpl(pref1, state, nstate);
+               final BGPRoute<IPv6Address> route2 = new BGPIPv6RouteImpl(pref2, state, nstate);
+               final BGPRoute<IPv6Address> route3 = new BGPIPv6RouteImpl(pref3, state, nstate);
+               addedObjects.add(route1);
+               addedObjects.add(route2);
+               addedObjects.add(route3);
+
+               return new BGPUpdateMessageImpl(addedObjects, Collections.<Identifier> emptySet());
+       }
+
+       @Test
+       public void testGetOpenMessage() throws DeserializerException, DocumentedException, IOException {
+               final Map<byte[], BGPMessage> openMap = Maps.newHashMap();
+
+               final Set<BGPTableType> type = Sets.newHashSet();
+               type.add(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.MPLSLabeledVPN));
+
+               final List<BGPParameter> params = Lists.newArrayList();
+               params.add(new MultiprotocolCapability(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.MPLSLabeledVPN)));
+
+               final byte[] input = new byte[] { 5, 8, 13, 21 };
+
+               openMap.put(input, new BGPOpenMessage(new ASNumber(30), (short) 30, null, params));
+
+               final BGPMessageParserMock mockParser = new BGPMessageParserMock(openMap);
+
+               final Set<BGPTableType> result = Sets.newHashSet();
+               for (final BGPParameter p : ((BGPOpenMessage) mockParser.parse(input, null)).getOptParams()) {
+                       if (p instanceof MultiprotocolCapability) {
+                               result.add(((MultiprotocolCapability) p).getTableType());
+                       }
+               }
+
+               assertEquals(type, result);
+
+               mockParser.close();
+       }
+}
diff --git a/bgp/parser-mock/src/test/resources/up0.bin b/bgp/parser-mock/src/test/resources/up0.bin
new file mode 100644 (file)
index 0000000..42e1b36
Binary files /dev/null and b/bgp/parser-mock/src/test/resources/up0.bin differ
diff --git a/bgp/parser-mock/src/test/resources/up1.bin b/bgp/parser-mock/src/test/resources/up1.bin
new file mode 100644 (file)
index 0000000..8fa2b21
Binary files /dev/null and b/bgp/parser-mock/src/test/resources/up1.bin differ
diff --git a/bgp/parser-mock/src/test/resources/up10.bin b/bgp/parser-mock/src/test/resources/up10.bin
new file mode 100644 (file)
index 0000000..ecd5f6d
Binary files /dev/null and b/bgp/parser-mock/src/test/resources/up10.bin differ
diff --git a/bgp/parser-mock/src/test/resources/up2.bin b/bgp/parser-mock/src/test/resources/up2.bin
new file mode 100644 (file)
index 0000000..ec30102
--- /dev/null
@@ -0,0 +1,2 @@
+\14\13\12\11\10\ f\ e\r\f\v
+       \b\a\ 6\ 5\ 4\ 3\ 2\ 1
\ No newline at end of file
diff --git a/bgp/parser-mock/src/test/resources/up3.bin b/bgp/parser-mock/src/test/resources/up3.bin
new file mode 100644 (file)
index 0000000..a77521f
Binary files /dev/null and b/bgp/parser-mock/src/test/resources/up3.bin differ
diff --git a/bgp/parser-mock/src/test/resources/up4.bin b/bgp/parser-mock/src/test/resources/up4.bin
new file mode 100644 (file)
index 0000000..30184df
Binary files /dev/null and b/bgp/parser-mock/src/test/resources/up4.bin differ
diff --git a/bgp/parser-mock/src/test/resources/up5.bin b/bgp/parser-mock/src/test/resources/up5.bin
new file mode 100644 (file)
index 0000000..a476c08
Binary files /dev/null and b/bgp/parser-mock/src/test/resources/up5.bin differ
diff --git a/bgp/parser-mock/src/test/resources/up6.bin b/bgp/parser-mock/src/test/resources/up6.bin
new file mode 100644 (file)
index 0000000..8e41240
Binary files /dev/null and b/bgp/parser-mock/src/test/resources/up6.bin differ
diff --git a/bgp/parser-mock/src/test/resources/up7.bin b/bgp/parser-mock/src/test/resources/up7.bin
new file mode 100644 (file)
index 0000000..d00866f
Binary files /dev/null and b/bgp/parser-mock/src/test/resources/up7.bin differ
diff --git a/bgp/parser-mock/src/test/resources/up8.bin b/bgp/parser-mock/src/test/resources/up8.bin
new file mode 100644 (file)
index 0000000..1b1cb4d
Binary files /dev/null and b/bgp/parser-mock/src/test/resources/up8.bin differ
diff --git a/bgp/parser-mock/src/test/resources/up9.bin b/bgp/parser-mock/src/test/resources/up9.bin
new file mode 100644 (file)
index 0000000..523c29b
Binary files /dev/null and b/bgp/parser-mock/src/test/resources/up9.bin differ
diff --git a/bgp/pom.xml b/bgp/pom.xml
new file mode 100644 (file)
index 0000000..2c3856d
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>protocol-parent</artifactId>
+               <version>0.1</version>
+       </parent>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-parent</artifactId>
+       <description>BGP-related components</description>
+       <packaging>pom</packaging>
+       <version>1.0</version>
+       <name>${project.artifactId}</name>
+       
+       <modules>
+               <module>concepts</module>
+               <module>linkstate</module>
+        <module>parser-api</module>
+        <module>parser-impl</module>
+        <module>parser-mock</module>
+        <module>rib-api</module>
+        <module>rib-impl</module>
+        <module>testtool</module>
+        <module>rib-mock</module>
+        <module>util</module>
+    </modules>
+</project>
diff --git a/bgp/rib-api/.project b/bgp/rib-api/.project
new file mode 100644 (file)
index 0000000..9ffebdc
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>bgp-rib-api</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bgp/rib-api/pom.xml b/bgp/rib-api/pom.xml
new file mode 100644 (file)
index 0000000..edf3040
--- /dev/null
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>bgp-parent</artifactId>
+               <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-rib-api</artifactId>
+       <description>BGP RIB API</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-parser-api</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-linkstate</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <version>${junit.version}</version>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Import-Package>
+                            org.opendaylight.protocol.bgp.concepts,
+                            org.opendaylight.protocol.bgp.linkstate, 
+                            org.opendaylight.protocol.bgp.parser, 
+                            org.opendaylight.protocol.concepts,
+                                                       com.google.common.base,
+                                                       com.google.guava,
+                                                       org.slf4j,
+                                               </Import-Package>
+                                               <Export-Package>
+                            org.opendaylight.protocol.bgp.rib,
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>${checkstyle.version}</version>
+                               <configuration>
+                                       <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+                                       <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>BGP-RIB-API Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/AbstractRIBChangeListener.java b/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/AbstractRIBChangeListener.java
new file mode 100644 (file)
index 0000000..f802cd2
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.protocol.concepts.InitialListenerEvents;
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+
+@ThreadSafe
+public abstract class AbstractRIBChangeListener implements RIBEventListener {
+       @Override
+       synchronized public final void onRIBEvent(final RIBEvent event) {
+               onRIBEventImpl(event);
+       }
+
+       abstract protected void onRIBEventImpl(final RIBEvent event);
+
+       synchronized public final ListenerRegistration<RIBEventListener> register(final RIB rib) {
+               InitialListenerEvents<RIBEventListener, RIBEvent> ile = rib.registerListener(this);
+               for (RIBEvent e : ile.getEvents())
+                       onRIBEvent(e);
+
+               return ile.getRegistration();
+       }
+}
diff --git a/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIB.java b/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIB.java
new file mode 100644 (file)
index 0000000..040f3b0
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib;
+
+import org.opendaylight.protocol.concepts.InitialListenerEvents;
+
+public interface RIB {
+
+       public InitialListenerEvents<RIBEventListener, RIBEvent> registerListener(RIBEventListener listener);
+
+}
diff --git a/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBChangedEvent.java b/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBChangedEvent.java
new file mode 100644 (file)
index 0000000..538ea29
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.opendaylight.protocol.bgp.parser.BGPLinkState;
+import org.opendaylight.protocol.bgp.parser.BGPNodeState;
+import org.opendaylight.protocol.bgp.parser.BGPPrefixState;
+import org.opendaylight.protocol.bgp.parser.BGPRouteState;
+
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+import com.google.common.base.Preconditions;
+
+public final class RIBChangedEvent extends RIBEvent {
+       private final Map<LinkIdentifier, BGPLinkState> links;
+       private final Map<NodeIdentifier, BGPNodeState> nodes;
+       private final Map<PrefixIdentifier<?>, BGPPrefixState> prefixes;
+       private final Map<Prefix<?>, BGPRouteState<?>> routes;
+
+       public RIBChangedEvent(final Map<LinkIdentifier, BGPLinkState> links, final Map<NodeIdentifier, BGPNodeState> nodes,
+                       final Map<PrefixIdentifier<?>, BGPPrefixState> prefixes, final Map<Prefix<?>, BGPRouteState<?>> routes) {
+               super();
+               this.links = Collections.unmodifiableMap(Preconditions.checkNotNull(links));
+               this.nodes = Collections.unmodifiableMap(Preconditions.checkNotNull(nodes));
+               this.prefixes = Collections.unmodifiableMap(Preconditions.checkNotNull(prefixes));
+               this.routes = Collections.unmodifiableMap(Preconditions.checkNotNull(routes));
+       }
+
+       public RIBChangedEvent(final Map<Prefix<?>, BGPRouteState<?>> routes) {
+               this(Collections.<LinkIdentifier, BGPLinkState> emptyMap(), Collections.<NodeIdentifier, BGPNodeState> emptyMap(), Collections.<PrefixIdentifier<?>, BGPPrefixState> emptyMap(), routes);
+       }
+
+       public RIBChangedEvent(final Map<LinkIdentifier, BGPLinkState> links, final Map<NodeIdentifier, BGPNodeState> nodes,
+                       final Map<PrefixIdentifier<?>, BGPPrefixState> prefixes) {
+               this(links, nodes, prefixes, Collections.<Prefix<?>, BGPRouteState<?>> emptyMap());
+       }
+
+       /**
+        * @return the links
+        */
+       public final Map<LinkIdentifier, BGPLinkState> getLinks() {
+               return this.links;
+       }
+
+       /**
+        * @return the nodes
+        */
+       public final Map<NodeIdentifier, BGPNodeState> getNodes() {
+               return this.nodes;
+       }
+
+       /**
+        * @return the prefixes
+        */
+       public final Map<PrefixIdentifier<?>, BGPPrefixState> getPrefixes() {
+               return this.prefixes;
+       }
+
+       /**
+        * @return the routes
+        */
+       public final Map<Prefix<?>, BGPRouteState<?>> getRoutes() {
+               return this.routes;
+       }
+}
diff --git a/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBEvent.java b/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBEvent.java
new file mode 100644 (file)
index 0000000..2e63d58
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib;
+
+public abstract class RIBEvent {
+       protected RIBEvent() {
+
+       }
+}
diff --git a/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBEventListener.java b/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBEventListener.java
new file mode 100644 (file)
index 0000000..3475ae3
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib;
+
+import java.util.EventListener;
+
+public interface RIBEventListener extends EventListener {
+       void onRIBEvent(RIBEvent event);
+}
diff --git a/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBSynchronizedEvent.java b/bgp/rib-api/src/main/java/org/opendaylight/protocol/bgp/rib/RIBSynchronizedEvent.java
new file mode 100644 (file)
index 0000000..0c84165
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+
+public final class RIBSynchronizedEvent extends RIBEvent {
+       private final BGPTableType table;
+
+       public RIBSynchronizedEvent(final BGPTableType table) {
+               this.table = table;
+       }
+
+       public BGPTableType getTable() {
+               return table;
+       }
+}
diff --git a/bgp/rib-impl/.project b/bgp/rib-impl/.project
new file mode 100644 (file)
index 0000000..c4e57bb
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>bgp-rib-impl</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bgp/rib-impl/pom.xml b/bgp/rib-impl/pom.xml
new file mode 100644 (file)
index 0000000..885fe7f
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>bgp-parent</artifactId>
+               <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-rib-impl</artifactId>
+       <description>BGP RIB implementation</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-linkstate</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-rib-api</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-util</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <version>${junit.version}</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>mockito-configuration</artifactId>
+                       <version>1.0</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-parser-impl</artifactId>
+                       <version>1.0</version>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Import-Package>
+                            org.opendaylight.protocol.concepts,
+                            org.opendaylight.protocol.framework,
+                                                       com.google.common.base,
+                            com.google.common.collect,
+                            com.google.common.eventbus,
+                            javax.annotation,
+                            javax.management,
+                            org.opendaylight.protocol.bgp.concepts,
+                            org.opendaylight.protocol.bgp.linkstate,
+                            org.opendaylight.protocol.bgp.parser,
+                            org.opendaylight.protocol.bgp.parser.impl,
+                            org.opendaylight.protocol.bgp.parser.message,
+                            org.opendaylight.protocol.bgp.parser.parameter,
+                            org.opendaylight.protocol.bgp.rib,
+                            org.opendaylight.protocol.bgp.util,
+                            org.opendaylight.protocol.util,
+                                                       org.slf4j,
+                                               </Import-Package>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.bgp.rib.impl
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>${checkstyle.version}</version>
+                               <configuration>
+                                       <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+                                       <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>BGP-RIB-IMPL Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGP.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGP.java
new file mode 100644 (file)
index 0000000..c5e81e2
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.IOException;
+
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+
+/**
+ * BGP interface. At this time it only supports listening to changes seen by the backing device, typically a network
+ * element. Abstracts away connection issues - listener starts getting notifications once connection is established.
+ * Implementation of this interface is required to send all previous messages.
+ */
+public interface BGP {
+       /**
+        * Register for BGP update feed. Specified listener will have the BGP information synchronized. The registration
+        * needs to be explicitly closed in order to stop receiving the updates.
+        * 
+        * @param listener {@link BGPSessionListener}
+        * @throws IllegalStateException if there is already a listener registered
+        * @throws IOException if some IO error occurred
+        * @return ListenerRegistration
+        */
+       public ListenerRegistration<BGPSessionListener> registerUpdateListener(BGPSessionListener listener) throws IOException;
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPConnectionImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPConnectionImpl.java
new file mode 100644 (file)
index 0000000..0886a53
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposalChecker;
+
+
+/**
+ * Implementation of {@link BGPConnection}.
+ */
+public class BGPConnectionImpl implements BGPConnection {
+
+       private final InetSocketAddress address;
+
+       private final BGPSessionListener listener;
+
+       private final BGPSessionPreferences proposal;
+
+       private final BGPSessionProposalChecker checker;
+
+       /**
+        * Merges together BGP specific connection attributes.
+        * 
+        * @param address inet socket address
+        * @param listener bgp session listener
+        * @param proposal bgp session preferences
+        * @param checker bgp session proposal checker
+        */
+       public BGPConnectionImpl(final InetSocketAddress address, final BGPSessionListener listener, final BGPSessionPreferences proposal,
+                       final BGPSessionProposalChecker checker) {
+               super();
+               this.address = address;
+               this.listener = listener;
+               this.proposal = proposal;
+               this.checker = checker;
+       }
+
+       @Override
+       public InetSocketAddress getPeerAddress() {
+               return this.address;
+       }
+
+       @Override
+       public BGPSessionListener getListener() {
+               return this.listener;
+       }
+
+       @Override
+       public BGPSessionPreferences getProposal() {
+               return this.proposal;
+       }
+
+       @Override
+       public BGPSessionProposalChecker getProposalChecker() {
+               return this.checker;
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPDispatcherImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPDispatcherImpl.java
new file mode 100644 (file)
index 0000000..492e758
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
+
+import org.opendaylight.protocol.framework.Dispatcher;
+
+/**
+ * Implementation of BGPDispatcher.
+ */
+public final class BGPDispatcherImpl implements BGPDispatcher, Closeable {
+
+       private final Dispatcher dispatcher;
+
+       public BGPDispatcherImpl(final Dispatcher dispatcher) throws IOException {
+               this.dispatcher = dispatcher;
+       }
+
+       @Override
+       public BGPSession createClient(final BGPConnection connection, final BGPMessageParser parser) throws IOException {
+               return (BGPSession) this.dispatcher.createClient(connection, new BGPSessionFactory(parser), BGPInputStream.FACTORY);
+       }
+
+       public Dispatcher getDispatcher() {
+               return this.dispatcher;
+       }
+
+       @Override
+       public void close() {
+               // This is only necessary for configuration interaction
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPImpl.java
new file mode 100644 (file)
index 0000000..a602248
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposal;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposalChecker;
+
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+
+/**
+ * Implementation of {@link BGP}.
+ */
+public class BGPImpl implements BGP, Closeable {
+       /**
+        * Wrapper class to give listener a close method.
+        */
+       public class BGPListenerRegistration implements ListenerRegistration<BGPSessionListener> {
+
+               private final BGPSessionListener listener;
+
+               private final BGPSession session;
+
+               public BGPListenerRegistration(final BGPSessionListener l, final BGPSession session) {
+                       this.listener = l;
+                       this.session = session;
+               }
+
+               @Override
+               public void close() {
+                       this.session.close();
+               }
+
+               @Override
+               public BGPSessionListener getListener() {
+                       return this.listener;
+               }
+       }
+
+       private final BGPDispatcher dispatcher;
+
+       private final BGPMessageParser parser;
+
+       private final InetSocketAddress address;
+
+       private final BGPSessionProposal proposal;
+
+       private final BGPSessionProposalChecker checker;
+
+       public BGPImpl(final BGPDispatcher dispatcher, final BGPMessageParser parser, final InetSocketAddress address,
+                       final BGPSessionProposal proposal, final BGPSessionProposalChecker checker) throws IOException {
+               this.dispatcher = dispatcher;
+               this.parser = parser;
+               this.address = address;
+               this.proposal = proposal;
+               this.checker = checker;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public ListenerRegistration<BGPSessionListener> registerUpdateListener(final BGPSessionListener listener) throws IOException {
+               final BGPSession session = this.dispatcher.createClient(
+                               new BGPConnectionImpl(this.address, listener, this.proposal.getProposal(), this.checker), this.parser);
+               return new BGPListenerRegistration(listener, session);
+       }
+
+       @Override
+       public void close() {
+
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPInputStream.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPInputStream.java
new file mode 100644 (file)
index 0000000..fd5f25a
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.util.ByteArray;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolInputStream;
+import org.opendaylight.protocol.framework.ProtocolInputStreamFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Input stream for BGP.
+ */
+public class BGPInputStream implements ProtocolInputStream {
+
+       private final static Logger logger = LoggerFactory.getLogger(BGPInputStream.class);
+
+       /**
+        * BGP implementation for protocol input stream factory.
+        */
+       public static final ProtocolInputStreamFactory FACTORY = new ProtocolInputStreamFactory() {
+               @Override
+               public ProtocolInputStream getProtocolInputStream(final PipedInputStream pis, final ProtocolMessageFactory factory) {
+                       return new BGPInputStream(pis, factory);
+               }
+       };
+
+       private final ProtocolMessageFactory factory;
+
+       private final PipedInputStream inputStream;
+
+       @VisibleForTesting
+       protected BGPMessageHeader header;
+
+       private BGPInputStream(final PipedInputStream inputStream, final ProtocolMessageFactory factory) {
+               this.factory = factory;
+               this.inputStream = inputStream;
+               this.header = new BGPMessageHeader();
+       }
+
+       /**
+        * Check availability of a message in underlying input stream. A message is available when there are more or the
+        * same amount of bytes in the stream as the message length is specified in message header. If there are not enough
+        * bytes for the message or even to read a message header, return false.
+        * 
+        * @return true if there are enough bytes to read a message false if there are not enough bytes to read a message or
+        *         a message header.
+        * @throws IOException
+        */
+       @Override
+       public synchronized boolean isMessageAvailable() throws IOException {
+               if (!this.header.isParsed()) {
+                       // No header, try to parse it
+                       this.header = (BGPMessageHeader) parseHeaderIfAvailable();
+
+                       if (!this.header.isParsed()) {
+                               // No luck, we do not have a message
+                               return false;
+                       }
+               }
+               // message length contains the size of the header too
+               if (this.inputStream.available() < (this.header.getLength() - BGPMessageHeader.COMMON_HEADER_LENGTH)) {
+                       return false;
+               }
+               return true;
+       }
+
+       /**
+        * If there are enough bytes in the underlying stream, parse the message. Blocking, till there are enough bytes to
+        * read, therefore the call of method isMessageAvailable() is suggested first.
+        * 
+        * @return protocol specific message
+        * @throws DeserializerException
+        * @throws IOException
+        * @throws DocumentedException
+        */
+       @Override
+       public synchronized BGPMessage getMessage() throws DeserializerException, IOException, DocumentedException {
+               // isMessageAvailable wasn't called, or there were not enough bytes to form message header
+               // blocking till the header is available
+               while (!this.header.isParsed()) {
+                       this.header = (BGPMessageHeader) parseHeaderIfAvailable();
+               }
+               final byte[] bytes = new byte[this.header.getLength() - BGPMessageHeader.COMMON_HEADER_LENGTH]; // message
+                                                                                                                                                                                                               // length
+                                                                                                                                                                                                               // contains the
+                                                                                                                                                                                                               // size of the
+                                                                                                                                                                                                               // header too
+               // blocking till the whole message is available
+               if (this.inputStream.read(bytes) == -1) {
+                       throw new IOException("PipedInputStream was closed, before data could be read from it.");
+               }
+
+               final BGPMessage msg = (BGPMessage) this.factory.parse(bytes, this.header);
+               this.header.setParsed(); // if we have all the bytes to send the message for parsing, clear the header, to let
+                                                                       // know,
+
+               return msg;
+       }
+
+       /**
+        * Checks if there are enough bytes to parse a header and parses it. Non-blocking: if there are not enough bytes to
+        * parse a message header, returns false.
+        * 
+        * @return cleared header if no header is available
+        * @return header object when enough data is available
+        */
+       private ProtocolMessageHeader parseHeaderIfAvailable() throws IOException {
+               final byte[] messageHeader = new byte[BGPMessageHeader.COMMON_HEADER_LENGTH];
+               if (this.inputStream.available() < BGPMessageHeader.COMMON_HEADER_LENGTH || this.inputStream.read(messageHeader) == -1) {
+                       this.header.setParsed();
+                       return this.header;
+               }
+               logger.debug("Attempt to parse BGP message header from bytes: {}", ByteArray.bytesToHexString(messageHeader));
+               return this.header.fromBytes(messageHeader);
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPObjectComparator.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPObjectComparator.java
new file mode 100644 (file)
index 0000000..bf15c3e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Comparator;
+
+import org.opendaylight.protocol.bgp.parser.AbstractBGPObjectState;
+
+
+/**
+ * This comparator is intended to implement BGP Best Path Selection algorithm, as described at
+ * 
+ * @see http://www.cisco.com/en/US/tech/tk365/technologies_tech_note09186a0080094431.shtml
+ * 
+ * @param <T> Actual object state reference
+ */
+final class BGPObjectComparator<T extends AbstractBGPObjectState<?>> implements Comparator<T> {
+       @Override
+       public int compare(final T o1, final T o2) {
+               if (o1 == o2)
+                       return 0;
+               if (o1 == null)
+                       return 1;
+               if (o2 == null)
+                       return -1;
+
+               // FIXME: look at ASPath
+               // FIXME: look at everything else :-)
+
+               return 0;
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java
new file mode 100644 (file)
index 0000000..be06242
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class representing a peer. We have a single instance for each peer, which provides translation from BGP events into
+ * RIB actions.
+ */
+public final class BGPPeer extends BGPSessionListener {
+       private static final Logger logger = LoggerFactory.getLogger(BGPPeer.class);
+       private Set<BGPTableType> tables;
+       private final String name;
+       private final RIBImpl rib;
+
+       public BGPPeer(final RIBImpl rib, final String name) {
+               this.rib = Preconditions.checkNotNull(rib);
+               this.name = Preconditions.checkNotNull(name);
+       }
+
+       @Override
+       public void onMessage(final BGPMessage message) {
+               if (message instanceof BGPUpdateMessage) {
+                       final BGPUpdateMessage m = (BGPUpdateMessage) message;
+                       this.rib.updateTables(this, m.getAddedObjects(), m.getRemovedObjects());
+               } else
+                       logger.info("Ignoring unhandled message class " + message.getClass());
+       }
+
+       @Override
+       public void onSessionUp(final Set<BGPTableType> remoteParams) {
+               logger.info("Session with peer {} went up with tables: {}", this.name, remoteParams);
+       }
+
+       @Override
+       public void onSessionDown(final BGPSession session, final Exception e) {
+               // FIXME: support graceful restart
+               for (final BGPTableType t : this.tables)
+                       this.rib.clearTable(this, t);
+       }
+
+       @Override
+       public void onSessionTerminated(final BGPError cause) {
+               logger.info("Session with peer {} terminated", this.name);
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("name", this.name);
+               toStringHelper.add("tables", this.tables);
+               return toStringHelper;
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionFactory.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionFactory.java
new file mode 100644 (file)
index 0000000..56fb033
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Timer;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+
+import org.opendaylight.protocol.framework.ProtocolConnection;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.ProtocolSessionFactory;
+import org.opendaylight.protocol.framework.SessionParent;
+
+/**
+ *
+ */
+public final class BGPSessionFactory implements ProtocolSessionFactory {
+
+       private final BGPMessageParser parser;
+
+       public BGPSessionFactory(final BGPMessageParser parser) {
+               this.parser = parser;
+       }
+
+       @Override
+       public ProtocolSession getProtocolSession(final SessionParent parent, final Timer timer, final ProtocolConnection connection,
+                       final int sessionId) {
+               return new BGPSessionImpl(parent, timer, (BGPConnection) connection, sessionId, this.parser);
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionImpl.java
new file mode 100644 (file)
index 0000000..e1ce972
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposalChecker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolOutputStream;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.SessionParent;
+import com.google.common.collect.Sets;
+
+class BGPSessionImpl implements BGPSession, ProtocolSession {
+
+       private static final Logger logger = LoggerFactory.getLogger(BGPSessionImpl.class);
+
+       /**
+        * KeepAlive Timer is to be scheduled periodically, each time it starts, it sends KeepAlive Message.
+        */
+       private class KeepAliveTimer extends TimerTask {
+               private final BGPSessionImpl parent;
+
+               public KeepAliveTimer(final BGPSessionImpl parent) {
+                       this.parent = parent;
+               }
+
+               @Override
+               public void run() {
+                       this.parent.handleKeepaliveTimer();
+               }
+       }
+
+       /**
+        * HoldTimer is to be scheduled periodically, when it expires, it closes BGP session.
+        */
+       private class HoldTimer extends TimerTask {
+               private final BGPSessionImpl parent;
+
+               public HoldTimer(final BGPSessionImpl parent) {
+                       this.parent = parent;
+               }
+
+               @Override
+               public void run() {
+                       this.parent.handleHoldTimer();
+               }
+       }
+
+       private static final int DEFAULT_HOLD_TIMER_VALUE = 15;
+
+       public static int HOLD_TIMER_VALUE = DEFAULT_HOLD_TIMER_VALUE; // 240
+
+       public int KEEP_ALIVE_TIMER_VALUE;
+
+       /**
+        * Possible states for Finite State Machine
+        */
+       private enum State {
+               IDLE, OPEN_SENT, OPEN_CONFIRM, ESTABLISHED
+       }
+
+       /**
+        * Actual state of the FSM.
+        */
+       private State state;
+
+       /**
+        * System.nanoTime value about when was sent the last message Protected to be updated also in tests.
+        */
+       protected long lastMessageSentAt;
+
+       /**
+        * System.nanoTime value about when was received the last message
+        */
+       private long lastMessageReceivedAt;
+
+       private final int sessionId;
+
+       private final BGPSessionListener listener;
+
+       /**
+        * Open message with session characteristics that were accepted by another BGP (sent from this session).
+        */
+       private BGPSessionPreferences localOpen = null;
+
+       /**
+        * Open Object with session characteristics for this session (sent from another BGP speaker).
+        */
+       private BGPSessionPreferences remoteOpen = null;
+
+       private final ProtocolOutputStream outputStream;
+
+       /**
+        * Timer object grouping FSM Timers
+        */
+       private final Timer stateTimer;
+
+       private final SessionParent parent;
+
+       private final BGPMessageParser parser;
+
+       private final BGPSessionProposalChecker checker;
+
+       private final BGPSynchronization sync;
+
+       private int kaCounter = 0;
+
+       BGPSessionImpl(final SessionParent parent, final Timer timer, final BGPConnection connection, final int sessionId,
+                       final BGPMessageParser parser) {
+               this.state = State.IDLE;
+               this.listener = connection.getListener();
+               this.sessionId = sessionId;
+               this.localOpen = connection.getProposal();
+               this.outputStream = new ProtocolOutputStream();
+               this.stateTimer = timer;
+               this.parent = parent;
+               this.parser = parser;
+               this.checker = connection.getProposalChecker();
+               this.sync = new BGPSynchronization(this.listener);
+       }
+
+       @Override
+       public void close() {
+               logger.debug("Closing session: " + this);
+               if (this.state == State.ESTABLISHED) {
+                       this.sendMessage(new BGPNotificationMessage(BGPError.CEASE));
+               }
+               this.changeState(State.IDLE);
+               this.parent.onSessionClosed(this);
+       }
+
+       @Override
+       public void startSession() {
+               logger.debug("Session started.");
+               this.sendMessage(new BGPOpenMessage(this.localOpen.getMyAs(), (short) this.localOpen.getHoldTime(), this.localOpen.getBgpId(), this.localOpen.getParams()));
+               this.stateTimer.schedule(new HoldTimer(this), DEFAULT_HOLD_TIMER_VALUE * 1000);
+               this.changeState(State.OPEN_SENT);
+       }
+
+       @Override
+       public ProtocolOutputStream getStream() {
+               return this.outputStream;
+       }
+
+       /**
+        * Handles incoming message based on their type.
+        * 
+        * @param msg incoming message
+        */
+       @Override
+       public void handleMessage(final ProtocolMessage msg) {
+               final BGPMessage bgpMsg = (BGPMessage) msg;
+               // Update last reception time
+               this.lastMessageReceivedAt = System.nanoTime();
+
+               // Open messages are handled internally, but are parsed also in bgp-parser, so notify bgp listener
+               if (bgpMsg instanceof BGPOpenMessage) {
+                       this.handleOpenMessage((BGPOpenMessage) bgpMsg);
+               }
+               // Keepalives are handled internally
+               else if (bgpMsg instanceof BGPKeepAliveMessage) {
+                       this.handleKeepAliveMessage();
+               }
+               // Notifications are handled internally
+               else if (bgpMsg instanceof BGPNotificationMessage) {
+                       logger.info("Session closed because Notification message received: {}" + ((BGPNotificationMessage) bgpMsg).getError());
+                       this.closeWithoutMessage();
+                       this.listener.onSessionTerminated(((BGPNotificationMessage) bgpMsg).getError());
+               } else {
+                       this.listener.onMessage(bgpMsg);
+               }
+       }
+
+       @Override
+       public void handleMalformedMessage(final DeserializerException e) {
+               logger.warn("Received malformed message: {}", e.getMessage(), e);
+               this.terminate(BGPError.FSM_ERROR);
+       }
+
+       @Override
+       public void handleMalformedMessage(final DocumentedException e) {
+               logger.warn("Received malformed message: {}", e.getMessage(), e);
+               this.terminate(((BGPDocumentedException) e).getError());
+       }
+
+       @Override
+       public void endOfInput() {
+               if (this.state != State.IDLE) {
+                       this.listener.onSessionDown(this, new IOException("End of input detected. Close the session."));
+               }
+       }
+
+       @Override
+       public ProtocolMessageFactory getMessageFactory() {
+               return this.parser;
+       }
+
+       @Override
+       public void onConnectionFailed(final IOException e) {
+               logger.info("Connection failed before finishing: {}", e.getMessage(), e);
+               this.listener.onSessionDown(this, e);
+       }
+
+       @Override
+       public int maximumMessageSize() {
+               return 4096;
+       }
+
+       void sendMessage(final BGPMessage msg) {
+               this.outputStream.putMessage(msg, this.parser);
+               this.lastMessageSentAt = System.nanoTime();
+               logger.debug("Sent message: " + msg);
+               this.parent.checkOutputBuffer(this);
+       }
+
+       private void closeWithoutMessage() {
+               logger.debug("Closing session: " + this);
+               HOLD_TIMER_VALUE = DEFAULT_HOLD_TIMER_VALUE;
+               this.changeState(State.IDLE);
+               this.parent.onSessionClosed(this);
+       }
+
+       /**
+        * Closes PCEP session from the parent with given reason. A message needs to be sent, but parent doesn't have to be
+        * modified, because he initiated the closing. (To prevent concurrent modification exception).
+        * 
+        * @param closeObject
+        */
+       private void terminate(final BGPError error) {
+               this.sendMessage(new BGPNotificationMessage(error));
+               this.closeWithoutMessage();
+               this.listener.onSessionTerminated(error);
+       }
+
+       /**
+        * If HoldTimer expires, the session ends. If a message (whichever) was received during this period, the HoldTimer
+        * will be rescheduled by HOLD_TIMER_VALUE + the time that has passed from the start of the HoldTimer to the time at
+        * which the message was received. If the session was closed by the time this method starts to execute (the session
+        * state will become IDLE), then rescheduling won't occur.
+        */
+       private synchronized void handleHoldTimer() {
+               final long ct = System.nanoTime();
+
+               final long nextHold = (long) (this.lastMessageReceivedAt + (HOLD_TIMER_VALUE * 1E9));
+
+               if (this.state != State.IDLE) {
+                       if (ct >= nextHold) {
+                               logger.debug("HoldTimer expired. " + new Date());
+                               this.terminate(BGPError.HOLD_TIMER_EXPIRED);
+                               return;
+                       }
+                       this.stateTimer.schedule(new HoldTimer(this), (long) ((nextHold - ct) / 1E6));
+               }
+       }
+
+       /**
+        * If KeepAlive Timer expires, sends KeepAlive message. If a message (whichever) was send during this period, the
+        * KeepAlive Timer will be rescheduled by KEEP_ALIVE_TIMER_VALUE + the time that has passed from the start of the
+        * KeepAlive timer to the time at which the message was sent. If the session was closed by the time this method
+        * starts to execute (the session state will become IDLE), that rescheduling won't occur.
+        */
+       private synchronized void handleKeepaliveTimer() {
+               final long ct = System.nanoTime();
+
+               long nextKeepalive = (long) (this.lastMessageSentAt + (this.KEEP_ALIVE_TIMER_VALUE * 1E9));
+
+               if (this.state == State.ESTABLISHED) {
+                       if (ct >= nextKeepalive) {
+                               this.sendMessage(new BGPKeepAliveMessage());
+                               nextKeepalive = (long) (this.lastMessageSentAt + (this.KEEP_ALIVE_TIMER_VALUE * 1E9));
+                       }
+                       this.stateTimer.schedule(new KeepAliveTimer(this), (long) ((nextKeepalive - ct) / 1E6));
+               }
+       }
+
+       private void changeState(final State finalState) {
+               final String desc = "Changed to state: ";
+               switch (finalState) {
+               case IDLE:
+                       logger.debug(desc + State.IDLE);
+                       this.state = State.IDLE;
+                       return;
+               case OPEN_SENT:
+                       logger.debug(desc + State.OPEN_SENT);
+                       if (this.state != State.IDLE) {
+                               throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.OPEN_SENT);
+                       }
+                       this.state = State.OPEN_SENT;
+                       return;
+               case OPEN_CONFIRM:
+                       logger.debug(desc + State.OPEN_CONFIRM);
+                       if (this.state == State.ESTABLISHED) {
+                               throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.OPEN_CONFIRM);
+                       }
+                       this.state = State.OPEN_CONFIRM;
+                       return;
+               case ESTABLISHED:
+                       logger.debug(desc + State.ESTABLISHED);
+                       if (this.state != State.OPEN_CONFIRM) {
+                               throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.ESTABLISHED);
+                       }
+                       this.state = State.ESTABLISHED;
+                       return;
+               }
+       }
+
+       /**
+        * Open message should be handled only if the FSM is in OPEN_SENT or IDLE state. When in IDLE state, the Open
+        * message was received _before_ local Open message was sent. When in OPEN_SENT state, the message was received
+        * _after_ local Open message was sent.
+        * 
+        * @param msg received Open Message.
+        */
+       private void handleOpenMessage(final BGPOpenMessage msg) {
+               this.remoteOpen = new BGPSessionPreferences(msg.getMyAS(), msg.getHoldTime(), msg.getBgpId(), msg.getOptParams());
+               logger.debug("Received message: {}", msg.toString());
+               if (this.state != State.IDLE && this.state != State.OPEN_SENT) {
+                       this.terminate(BGPError.FSM_ERROR);
+                       return;
+               }
+               // if the session characteristics were unacceptable, the session is terminated
+               // with given BGP error
+               try {
+                       this.checker.checkSessionCharacteristics(this.remoteOpen);
+               } catch (final BGPDocumentedException e) {
+                       this.terminate(e.getError());
+               }
+               // the session characteristics were acceptable
+               HOLD_TIMER_VALUE = this.remoteOpen.getHoldTime();
+               logger.debug("Session chars are acceptable. Overwriting: holdtimer: {}", HOLD_TIMER_VALUE);
+               // when in IDLE state, we haven't send Open Message yet, do it now
+               if (this.state == State.IDLE) {
+                       this.sendMessage(new BGPOpenMessage(this.localOpen.getMyAs(), (short) this.localOpen.getHoldTime(), this.localOpen.getBgpId(), this.localOpen.getParams()));
+               }
+               this.sendMessage(new BGPKeepAliveMessage());
+               // if the timer is not disabled
+               if (HOLD_TIMER_VALUE != 0) {
+                       this.KEEP_ALIVE_TIMER_VALUE = HOLD_TIMER_VALUE / 3;
+                       this.stateTimer.schedule(new KeepAliveTimer(this), this.KEEP_ALIVE_TIMER_VALUE * 1000);
+                       this.stateTimer.schedule(new HoldTimer(this), HOLD_TIMER_VALUE * 1000);
+               }
+               this.changeState(State.OPEN_CONFIRM);
+       }
+
+       /**
+        * KeepAlive message should be explicitly parsed in FSM when its state is OPEN_CONFIRM. Otherwise is handled by the
+        * KeepAliveTimer or it's invalid.
+        */
+       private void handleKeepAliveMessage() {
+               logger.debug("Received KeepAlive messsage.");
+               if (this.state == State.OPEN_CONFIRM) {
+                       if (HOLD_TIMER_VALUE != 0) {
+                               this.stateTimer.schedule(new HoldTimer(this), HOLD_TIMER_VALUE * 1000);
+                               this.stateTimer.schedule(new KeepAliveTimer(this), this.KEEP_ALIVE_TIMER_VALUE * 1000);
+                       }
+                       this.changeState(State.ESTABLISHED);
+                       final Set<BGPTableType> tts = Sets.newHashSet();
+                       if (this.remoteOpen.getParams() != null) {
+                               for (final BGPParameter param : this.remoteOpen.getParams()) {
+                                       if (param instanceof MultiprotocolCapability) {
+                                               tts.add(((MultiprotocolCapability) param).getTableType());
+                                       }
+                               }
+                       }
+                       this.sync.addTableTypes(tts);
+                       this.listener.onSessionUp(tts);
+                       // check if the KA is EOR for some AFI/SAFI
+               } else if (this.state == State.ESTABLISHED) {
+                       this.kaCounter++;
+                       if (this.kaCounter >= 2) {
+                               this.sync.kaReceived();
+                       }
+               }
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("BGPSessionImpl [state=");
+               builder.append(this.state);
+               builder.append(", sessionId=");
+               builder.append(this.sessionId);
+               builder.append(", localOpen=");
+               builder.append(this.localOpen);
+               builder.append(", remoteOpen=");
+               builder.append(this.remoteOpen);
+               builder.append(", outputStream=");
+               builder.append(this.outputStream);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionProposalCheckerImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionProposalCheckerImpl.java
new file mode 100644 (file)
index 0000000..a8999d9
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposalChecker;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+
+/**
+ * Basic implementation of BGP Session Proposal Checker. Session characteristics are always acceptable.
+ */
+public final class BGPSessionProposalCheckerImpl extends BGPSessionProposalChecker implements Closeable {
+
+       public BGPSessionProposalCheckerImpl() {
+
+       }
+
+       @Override
+       public SessionPreferences getNewProposal(final SessionPreferences oldOpen) {
+               throw new IllegalStateException("This method shoudln't be called in BGP.");
+       }
+
+       @Override
+       public Boolean checkSessionCharacteristics(final SessionPreferences openObj) throws BGPDocumentedException {
+               return true;
+       }
+
+       @Override
+       public void close() throws IOException {
+               // nothing to close
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionProposalImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionProposalImpl.java
new file mode 100644 (file)
index 0000000..9c7e141
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.List;
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.parameter.AS4BytesCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposal;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.collect.Lists;
+
+/**
+ * Basic implementation of BGP Session Proposal. The values are taken from conf-bgp.
+ */
+public final class BGPSessionProposalImpl extends BGPSessionProposal implements Closeable {
+
+       private final short holdTimer;
+
+       private final ASNumber as;
+
+       private final IPv4Address bgpId;
+
+       private final BGPSessionPreferences prefs;
+
+       public BGPSessionProposalImpl(final short holdTimer, final ASNumber as, final IPv4Address bgpId) {
+               this.holdTimer = holdTimer;
+               this.as = as;
+               this.bgpId = bgpId;
+
+               final BGPTableType ipv4 = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+               final BGPTableType linkstate = new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Linkstate);
+               final List<BGPParameter> tlvs = Lists.newArrayList();
+               tlvs.add(new MultiprotocolCapability(ipv4));
+               tlvs.add(new MultiprotocolCapability(linkstate));
+               // final Map<BGPTableType, Boolean> tableTypes = Maps.newHashMap();
+               // tableTypes.put(ipv4, true);
+               // tableTypes.put(linkstate,true);
+               // tlvs.add(new GracefulCapability(true, 0, tableTypes));
+               tlvs.add(new AS4BytesCapability(as));
+               this.prefs = new BGPSessionPreferences(as, holdTimer, bgpId, tlvs);
+
+       }
+
+       @Override
+       public BGPSessionPreferences getProposal() {
+               return this.prefs;
+       }
+
+       @Override
+       public void close() throws IOException {
+               // nothing to close
+       }
+
+       /**
+        * @return the holdTimer
+        */
+       public short getHoldTimer() {
+               return this.holdTimer;
+       }
+
+       /**
+        * @return the as
+        */
+       public ASNumber getAs() {
+               return this.as;
+       }
+
+       /**
+        * @return the bgpId
+        */
+       public IPv4Address getBgpId() {
+               return this.bgpId;
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSynchronization.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSynchronization.java
new file mode 100644 (file)
index 0000000..4acc545
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPLink;
+import org.opendaylight.protocol.bgp.parser.BGPNode;
+import org.opendaylight.protocol.bgp.parser.BGPPrefix;
+import org.opendaylight.protocol.bgp.parser.BGPRoute;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
+import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+/**
+ * BGP speaker (without Graceful restart capability) sends KeepAlive message after sending all initial Update messages
+ * with certain AFI/SAFI. For each AFI/SAFI, it sends one KA message. As it is undetermined which KA message belongs to
+ * which AFI/SAFI, an algorithm needed to be implemented.
+ */
+public class BGPSynchronization {
+
+       private static final Logger logger = LoggerFactory.getLogger(BGPSynchronization.class);
+
+       private class SyncVariables {
+
+               private boolean upd = false;
+               private boolean eor = false;
+
+               public void setUpd(final boolean upd) {
+                       this.upd = upd;
+               }
+
+               public void setEorTrue() {
+                       this.eor = true;
+               }
+
+               public boolean getEor() {
+                       return this.eor;
+               }
+
+               public boolean getUpd() {
+                       return this.upd;
+               }
+       }
+
+       private final Map<BGPTableType, SyncVariables> syncStorage = Maps.newHashMap();
+
+       private final BGPSessionListener listener;
+
+       public BGPSynchronization(final BGPSessionListener listener) {
+               this.listener = listener;
+       }
+
+       /**
+        * Fills in syncStorage map with BGPTableTypes received in speakers Open Message.
+        * 
+        * @param types BGPTableTypes from remote Open message
+        */
+       public void addTableTypes(final Set<BGPTableType> types) {
+               for (final BGPTableType type : types) {
+                       this.syncStorage.put(type, new SyncVariables());
+               }
+       }
+
+       /**
+        * For each received Update message, the upd sync variable needs to be updated to true, for particular AFI/SAFI
+        * combination. Currently we only assume Unicast SAFI. From the Update message we have to extract the AFI. Each
+        * Update message can contain BGP Object with one type of AFI. If the object is BGP Link, BGP Node or BGPPrefix<?>
+        * the AFI is Linkstate. In case of BGPRoute, the AFI depends on the IP Address of the prefix.
+        * 
+        * @param msg received Update message
+        */
+       public void updReceived(final BGPUpdateMessage msg) {
+               BGPTableType type = null;
+               if (!msg.getAddedObjects().isEmpty()) {
+                       final BGPObject obj = msg.getAddedObjects().iterator().next();
+                       if (obj instanceof BGPRoute<?>) {
+                               if (((BGPRoute<?>) obj) instanceof BGPIPv4RouteImpl) {
+                                       type = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+                               } else if (((BGPRoute<?>) obj) instanceof BGPIPv6RouteImpl) {
+                                       type = new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.Unicast);
+                               }
+                       } else if (obj instanceof BGPLink || obj instanceof BGPNode || obj instanceof BGPPrefix<?>) {
+                               type = new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Linkstate);
+                       }
+               }
+               final SyncVariables s = this.syncStorage.get(type);
+               if (s == null) {
+                       logger.warn("BGPTableType was not present in open message : {}", type);
+                       return;
+               }
+               s.setUpd(true);
+       }
+
+       /**
+        * This method is called, when the second KA message is received. It checks each AFI/SAFI sync variables. If they
+        * are all false, which means, that there was at least one update message followed by one KA, the EOR is sent to
+        * session.
+        */
+       public void kaReceived() {
+               for (final Entry<BGPTableType, SyncVariables> entry : this.syncStorage.entrySet()) {
+                       final SyncVariables s = entry.getValue();
+                       if (!s.getEor()) {
+                               if (!s.getUpd()) {
+                                       s.setEorTrue();
+                                       final BGPUpdateSynchronized up = generateEOR(entry.getKey());
+                                       logger.debug("Sending synchronization message: {}", up);
+                                       this.listener.onMessage(up);
+                               }
+                               s.setUpd(false);
+                       }
+               }
+       }
+
+       private BGPUpdateSynchronized generateEOR(final BGPTableType type) {
+               return new BGPUpdateSynchronizedImpl(type);
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPUpdateSynchronizedImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPUpdateSynchronizedImpl.java
new file mode 100644 (file)
index 0000000..6b2d848
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
+
+
+/**
+ *
+ */
+public class BGPUpdateSynchronizedImpl implements BGPUpdateSynchronized {
+
+       private static final long serialVersionUID = -3574952849467738325L;
+
+       private final BGPTableType tt;
+
+       public BGPUpdateSynchronizedImpl(final BGPTableType tt) {
+               this.tt = tt;
+       }
+
+       @Override
+       public BGPTableType getTableType() {
+               return this.tt;
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBEntry.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBEntry.java
new file mode 100644 (file)
index 0000000..c6952d7
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.protocol.bgp.parser.AbstractBGPObjectState;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.concepts.NamedObject;
+import com.google.common.base.Preconditions;
+
+/**
+ * A single RIB table entry, which holds multiple versions of the entry's state and elects the authoritative based on
+ * ordering specified by the supplied comparator.
+ * 
+ * @param <ID> Identifier type
+ * @param <STATE> State type
+ */
+@ThreadSafe
+final class RIBEntry<ID extends Identifier, STATE extends AbstractBGPObjectState<?>> implements NamedObject<ID> {
+       /*
+        * TODO: we could dramatically optimize performance by using the comparator
+        *       to retain the candidate states ordered -- thus selection would occur
+        *       automatically through insertion, without the need of a second walk.
+        */
+       private final Map<BGPPeer, STATE> candidates = new HashMap<>();
+       private final Comparator<STATE> comparator;
+       private STATE currentState = null;
+       private final ID name;
+
+       RIBEntry(final ID name, final Comparator<STATE> comparator) {
+               this.name = Preconditions.checkNotNull(name);
+               this.comparator = Preconditions.checkNotNull(comparator);
+       }
+
+       @Override
+       public ID getName() {
+               return this.name;
+       }
+
+       private STATE findCandidate(final STATE initial) {
+               STATE newState = initial;
+               for (final STATE s : this.candidates.values())
+                       if (this.comparator.compare(newState, s) > 0)
+                               newState = s;
+
+               return newState;
+       }
+
+       private void electCandidate(final Map<ID, STATE> transaction, final STATE candidate) {
+               if (this.currentState == null || !this.currentState.equals(candidate)) {
+                       transaction.put(this.name, candidate);
+                       this.currentState = candidate;
+               }
+       }
+
+       synchronized boolean removeState(final Map<ID, STATE> transaction, final BGPPeer peer) {
+               this.candidates.remove(peer);
+
+               final STATE candidate = findCandidate(null);
+               if (candidate != null) {
+                       electCandidate(transaction, candidate);
+                       return true;
+               } else
+                       return false;
+       }
+
+       synchronized void setState(final Map<ID, STATE> transaction, final BGPPeer peer, final STATE state) {
+               this.candidates.put(peer, state);
+               electCandidate(transaction, findCandidate(state));
+       }
+
+       synchronized STATE getState() {
+               return this.currentState;
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java
new file mode 100644 (file)
index 0000000..7c459a2
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPLink;
+import org.opendaylight.protocol.bgp.parser.BGPLinkState;
+import org.opendaylight.protocol.bgp.parser.BGPNode;
+import org.opendaylight.protocol.bgp.parser.BGPNodeState;
+import org.opendaylight.protocol.bgp.parser.BGPPrefix;
+import org.opendaylight.protocol.bgp.parser.BGPPrefixState;
+import org.opendaylight.protocol.bgp.parser.BGPRoute;
+import org.opendaylight.protocol.bgp.parser.BGPRouteState;
+import org.opendaylight.protocol.bgp.rib.RIB;
+import org.opendaylight.protocol.bgp.rib.RIBChangedEvent;
+import org.opendaylight.protocol.bgp.rib.RIBEvent;
+import org.opendaylight.protocol.bgp.rib.RIBEventListener;
+
+import org.opendaylight.protocol.concepts.InitialListenerEvents;
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
+@ThreadSafe
+public final class RIBImpl implements RIB {
+       private final RIBTable<LinkIdentifier, BGPLinkState> links = new RIBTable<>();
+       private final RIBTable<NodeIdentifier, BGPNodeState> nodes = new RIBTable<>();
+       private final RIBTable<PrefixIdentifier<?>, BGPPrefixState> prefixes = new RIBTable<>();
+       private final RIBTable<Prefix<?>, BGPRouteState<?>> routes = new RIBTable<>();
+       private final EventBus bus;
+       private final String name;
+
+       public RIBImpl(final String name) {
+               this.name = Preconditions.checkNotNull(name);
+               bus = new EventBus(name);
+       }
+
+       synchronized void updateTables(final BGPPeer peer, final Set<BGPObject> addedObjects, final Set<?> removedObjects) {
+               final Map<LinkIdentifier, BGPLinkState> l = new HashMap<>();
+               final Map<NodeIdentifier, BGPNodeState> n = new HashMap<>();
+               final Map<PrefixIdentifier<?>, BGPPrefixState> p = new HashMap<>();
+               final Map<Prefix<?>, BGPRouteState<?>> r = new HashMap<>();
+
+               for (final Object id : removedObjects)
+                       if (id instanceof Prefix<?>)
+                               routes.remove(r, peer, (Prefix<?>)id);
+                       else if (id instanceof LinkIdentifier)
+                               links.remove(l, peer, (LinkIdentifier)id);
+                       else if (id instanceof NodeIdentifier)
+                               nodes.remove(n, peer, (NodeIdentifier) id);
+                       else if (id instanceof PrefixIdentifier<?>)
+                               prefixes.remove(p, peer, (PrefixIdentifier<?>) id);
+                       else
+                               throw new IllegalArgumentException("Unsupported identifier " + id.getClass());
+
+               for (final BGPObject o : addedObjects)
+                       if (o instanceof BGPLink) {
+                               final BGPLink link = (BGPLink)o;
+                               links.add(l, peer, link.getLinkIdentifier(), link.currentState());
+                       } else if (o instanceof BGPNode) {
+                               final BGPNode node = (BGPNode)o;
+                               nodes.add(n, peer, node.getNodeIdentifier(), node.currentState());
+                       } else if (o instanceof BGPPrefix<?>) {
+                               final BGPPrefix<?> prefix = (BGPPrefix<?>)o;
+                               prefixes.add(p, peer, prefix.getPrefixIdentifier(), prefix.currentState());
+                       } else if (o instanceof BGPRoute<?> ) {
+                               final BGPRoute<?> route = (BGPRoute<?>)o;
+                               routes.add(r, peer, route.getName(), route.currentState());
+                       } else
+                               throw new IllegalArgumentException("Unsupported identifier " + o.getClass());
+
+               if (!l.isEmpty() || !n.isEmpty() || !p.isEmpty() || !r.isEmpty())
+                       bus.post(new RIBChangedEvent(l, n, p, r));
+       }
+
+       synchronized void clearTable(final BGPPeer peer, final BGPTableType t) {
+               switch (t.getAddressFamily()) {
+               case IPv4:
+               case IPv6:
+                       bus.post(new RIBChangedEvent(routes.clear(peer)));
+                       break;
+               case LinkState:
+                       bus.post(new RIBChangedEvent(links.clear(peer), nodes.clear(peer), prefixes.clear(peer)));
+                       break;
+               }
+       }
+
+       @Override
+       synchronized public InitialListenerEvents<RIBEventListener, RIBEvent> registerListener(final RIBEventListener listener) {
+               final List<RIBEvent> events = new ArrayList<>();
+
+               events.add(new RIBChangedEvent(routes.currentState()));
+               events.add(new RIBChangedEvent(links.currentState(), nodes.currentState(), prefixes.currentState()));
+
+               final Object wrapper = new Object() {
+                       @Subscribe
+                       public void notifyListener(final RIBChangedEvent event) {
+                               listener.onRIBEvent(event);
+                       }
+               };
+               bus.register(wrapper);
+
+               return new InitialListenerEvents<RIBEventListener, RIBEvent>(new ListenerRegistration<RIBEventListener>() {
+                       @Override
+                       public void close() {
+                               bus.unregister(wrapper);
+                       }
+
+                       @Override
+                       public RIBEventListener getListener() {
+                               return listener;
+                       }
+               }, events);
+       }
+
+       @Override
+       public final String toString(){
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("name", name);
+               return toStringHelper;
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBTable.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBTable.java
new file mode 100644 (file)
index 0000000..6990073
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.protocol.bgp.parser.AbstractBGPObjectState;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+@ThreadSafe
+class RIBTable<ID extends Identifier, STATE extends AbstractBGPObjectState<?>> {
+       private final Comparator<STATE> comparator = new BGPObjectComparator<>();
+       private final Map<ID, RIBEntry<ID, STATE>> entries = new HashMap<>();
+
+       RIBTable() {
+       }
+
+       synchronized void add(final Map<ID, STATE> transaction, final BGPPeer peer, final ID id, final STATE state) {
+               RIBEntry<ID, STATE> e = this.entries.get(id);
+               if (e == null) {
+                       e = new RIBEntry<ID, STATE>(id, this.comparator);
+                       this.entries.put(id, e);
+               }
+
+               e.setState(transaction, peer, state);
+       }
+
+       synchronized Map<ID, STATE> clear(final BGPPeer peer) {
+               final Map<ID, STATE> transaction = new HashMap<>();
+
+               final Iterator<Map.Entry<ID, RIBEntry<ID, STATE>>> i = this.entries.entrySet().iterator();
+               while (i.hasNext()) {
+                       final Map.Entry<ID, RIBEntry<ID, STATE>> e = i.next();
+
+                       if (e.getValue().removeState(transaction, peer))
+                               i.remove();
+               }
+
+               return transaction;
+       }
+
+       synchronized void remove(final Map<ID, STATE> transaction, final BGPPeer peer, final ID id) {
+               final RIBEntry<ID, STATE> e = this.entries.get(id);
+               if (e != null && e.removeState(transaction, peer))
+                       this.entries.remove(id);
+       }
+
+       synchronized Map<ID, STATE> currentState() {
+               final Map<ID, STATE> ret = new HashMap<>();
+
+               for (final Entry<ID, RIBEntry<ID, STATE>> e : this.entries.entrySet())
+                       ret.put(e.getKey(), e.getValue().getState());
+
+               return ret;
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPConnection.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPConnection.java
new file mode 100644 (file)
index 0000000..6902e45
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+
+import org.opendaylight.protocol.framework.ProtocolConnection;
+
+/**
+ * BGP specific connection attributes.
+ */
+public interface BGPConnection extends ProtocolConnection {
+
+       @Override
+       public BGPSessionListener getListener();
+
+       @Override
+       public BGPSessionPreferences getProposal();
+
+       @Override
+       public BGPSessionProposalChecker getProposalChecker();
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPConnectionFactory.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPConnectionFactory.java
new file mode 100644 (file)
index 0000000..65d1d45
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.ProtocolConnectionFactory;
+
+/**
+ * BGP implementation of {@link ProtocolConnectionFactory}
+ */
+public interface BGPConnectionFactory extends ProtocolConnectionFactory {
+       @Override
+       BGPConnection createProtocolConnection(final InetSocketAddress address);
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPDispatcher.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPDispatcher.java
new file mode 100644 (file)
index 0000000..92b2768
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import java.io.IOException;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+
+
+/**
+ * Dispatcher class for creating BGP clients.
+ */
+public interface BGPDispatcher {
+
+       /**
+        * Creates BGP client.
+        * 
+        * @param connection attributes required for connection
+        * @param parser BGP message parser
+        * @return client session
+        * @throws IOException
+        */
+       BGPSession createClient(BGPConnection connection, BGPMessageParser parser) throws IOException;
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionPreferences.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionPreferences.java
new file mode 100644 (file)
index 0000000..fc679d6
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import java.util.List;
+
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * DTO for BGP Session preferences, that contains BGP Open message.
+ */
+public final class BGPSessionPreferences implements SessionPreferences {
+
+       private final ASNumber as;
+
+       private final int hold;
+
+       private final IPv4Address bgpId;
+
+       private final List<BGPParameter> params;
+
+       /**
+        * Creates a new DTO for Open message.
+        * 
+        * @param prefs BGP Open message
+        */
+       public BGPSessionPreferences(final ASNumber as, final int hold, final IPv4Address bgpId, final List<BGPParameter> params) {
+               this.as = as;
+               this.hold = hold;
+               this.bgpId = bgpId;
+               this.params = params;
+       }
+
+       /**
+        * Returns my AS number.
+        * 
+        * @return AS number
+        */
+       public ASNumber getMyAs() {
+               return this.as;
+       }
+
+       /**
+        * Returns initial value of HoldTimer.
+        * 
+        * @return initial value of HoldTimer
+        */
+       public int getHoldTime() {
+               return this.hold;
+       }
+
+       /**
+        * Returns my BGP Identifier.
+        * 
+        * @return BGP identifier
+        */
+       public IPv4Address getBgpId() {
+               return this.bgpId;
+       }
+
+       public List<BGPParameter> getParams() {
+               return this.params;
+       }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionProposal.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionProposal.java
new file mode 100644 (file)
index 0000000..fa07dce
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import org.opendaylight.protocol.framework.SessionProposal;
+
+/**
+ * Interface that provides the initial acceptable session characteristics with which the session should be started.
+ */
+public abstract class BGPSessionProposal implements SessionProposal {
+       /**
+        * Returns BGPSessionPreferences for this IP address.
+        * 
+        * @param address serves as constraint, the implementation can also take time into consideration
+        * @return BGPSessionPreferences with acceptable session characteristics
+        */
+       @Override
+       public abstract BGPSessionPreferences getProposal();
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionProposalChecker.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionProposalChecker.java
new file mode 100644 (file)
index 0000000..a82124b
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.framework.SessionPreferencesChecker;
+
+/**
+ * Session characteristics initial proposal checker. BGP does not have any negotiation. If the characteristics are not
+ * acceptable, the session ends.
+ */
+public abstract class BGPSessionProposalChecker implements SessionPreferencesChecker {
+
+       @Override
+       public abstract Boolean checkSessionCharacteristics(final SessionPreferences openObj) throws BGPDocumentedException;
+}
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ApiTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ApiTest.java
new file mode 100644 (file)
index 0000000..4a336f1
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.AS4BytesCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.CapabilityParameter;
+import org.opendaylight.protocol.bgp.parser.parameter.GracefulCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.rib.impl.BGPUpdateSynchronizedImpl;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.collect.Maps;
+
+public class ApiTest {
+
+       @Test
+       public void testDocumentedException() {
+               final DocumentedException de = new BGPDocumentedException("Some message", BGPError.BAD_BGP_ID);
+               assertEquals("Some message", de.getMessage());
+               assertEquals(BGPError.BAD_BGP_ID, ((BGPDocumentedException) de).getError());
+               assertNull(((BGPDocumentedException) de).getData());
+       }
+
+       @Test
+       public void testBGPKeepAliveMessage() {
+               final BGPMessage msg = new BGPKeepAliveMessage();
+               assertTrue(msg instanceof BGPKeepAliveMessage);
+       }
+
+       @Test
+       public void testBGPNotificationMessage() {
+               final BGPMessage msg = new BGPNotificationMessage(BGPError.AS_PATH_MALFORMED);
+               assertTrue(msg instanceof BGPNotificationMessage);
+               assertEquals(BGPError.AS_PATH_MALFORMED, ((BGPNotificationMessage) msg).getError());
+               assertNull(((BGPNotificationMessage) msg).getData());
+       }
+
+       @Test
+       public void testBGPOpenMessage() {
+               final BGPMessage msg = new BGPOpenMessage(new ASNumber(58), (short) 5, null, null);
+               assertNull(((BGPOpenMessage) msg).getOptParams());
+       }
+
+       @Test
+       public void testBGPParameter() {
+
+               final BGPTableType t = new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Unicast);
+               final BGPTableType t1 = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+
+               final BGPParameter tlv1 = new MultiprotocolCapability(t);
+
+               final BGPParameter tlv2 = new MultiprotocolCapability(t1);
+
+               final Map<BGPTableType, Boolean> tt = Maps.newHashMap();
+               tt.put(t, true);
+               tt.put(t1, false);
+
+               final BGPParameter tlv3 = new GracefulCapability(false, 0, tt);
+
+               final BGPParameter tlv4 = new AS4BytesCapability(new ASNumber(40));
+
+               assertFalse(((GracefulCapability) tlv3).isRestartFlag());
+
+               assertEquals(0, ((GracefulCapability) tlv3).getRestartTimerValue());
+
+               assertEquals(tlv1.getType(), tlv2.getType());
+
+               assertFalse(tlv1.equals(tlv2));
+
+               assertNotSame(tlv1.hashCode(), tlv3.hashCode());
+
+               assertNotSame(tlv2.toString(), tlv3.toString());
+
+               assertEquals(((GracefulCapability) tlv3).getTableTypes(), tt);
+
+               assertNotSame(((CapabilityParameter) tlv1).getCode(), ((CapabilityParameter) tlv3).getCode());
+
+               assertEquals(((MultiprotocolCapability) tlv1).getSafi(), ((MultiprotocolCapability) tlv2).getSafi());
+
+               assertNotSame(((MultiprotocolCapability) tlv1).getAfi(), ((MultiprotocolCapability) tlv2).getAfi());
+
+               assertEquals(40, ((AS4BytesCapability) tlv4).getASNumber().getAsn());
+
+               assertEquals(new AS4BytesCapability(new ASNumber(40)).toString(), tlv4.toString());
+       }
+
+       @Test
+       public void testToString() {
+               final BGPMessage o = new BGPOpenMessage(new ASNumber(58), (short) 5, null, null);
+               final BGPMessage n = new BGPNotificationMessage(BGPError.ATTR_FLAGS_MISSING);
+               assertNotSame(o.toString(), n.toString());
+       }
+
+       @Test
+       public void testBGPSessionPreferences() {
+               final SessionPreferences sp = new BGPSessionPreferences(new ASNumber(58), (short) 5, null, null);
+               assertNull(((BGPSessionPreferences) sp).getBgpId());
+               assertEquals((short) 5, ((BGPSessionPreferences) sp).getHoldTime());
+               assertEquals(58, ((BGPSessionPreferences) sp).getMyAs().getAsn());
+       }
+
+       @Test
+       public void testBGPUpdateSynchronized() {
+               final BGPTableType tt = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Linkstate);
+               final BGPUpdateSynchronized update = new BGPUpdateSynchronizedImpl(tt);
+               assertEquals(tt, update.getTableType());
+       }
+}
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BGPImplTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BGPImplTest.java
new file mode 100644 (file)
index 0000000..2d72c1e
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.rib.impl.BGPImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPImpl.BGPListenerRegistration;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposal;
+
+
+public class BGPImplTest {
+
+       @Mock
+       private BGPDispatcher disp;
+
+       @Mock
+       private BGPSessionProposal prop;
+
+       @Mock
+       private BGPMessageParser parser;
+
+       private BGPImpl bgp;
+
+       @Before
+       public void setUp() throws IOException {
+               MockitoAnnotations.initMocks(this);
+               doReturn("").when(this.parser).toString();
+               doReturn(null).when(this.disp).createClient(any(BGPConnection.class), any(BGPMessageParser.class));
+       }
+
+       @Test
+       public void testBgpImpl() throws IOException {
+               doReturn(new BGPSessionPreferences(null, 0, null, Collections.<BGPParameter> emptyList())).when(this.prop).getProposal();
+               this.bgp = new BGPImpl(this.disp, this.parser, null, this.prop, null);
+               final BGPListenerRegistration reg = (BGPListenerRegistration) this.bgp.registerUpdateListener(new SimpleSessionListener());
+               assertEquals(SimpleSessionListener.class, reg.getListener().getClass());
+       }
+
+       @After
+       public void tearDown() {
+               this.bgp.close();
+       }
+}
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/FSMTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/FSMTest.java
new file mode 100644 (file)
index 0000000..71dd471
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionImpl;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+public class FSMTest {
+
+       private SimpleSessionListener clientListener;
+
+       private final SpeakerSessionListener speakerListener = new SpeakerSessionListener();
+
+       private SpeakerSessionMock speaker;
+
+       @Before
+       public void setUp() {
+               this.clientListener = new SimpleSessionListener();
+               this.speaker = new SpeakerSessionMock(this.speakerListener, this.clientListener);
+               this.clientListener.addSession(this.speaker);
+       }
+
+       @Test
+       public void testAccSessionChar() throws InterruptedException {
+               this.speaker.startSession();
+               assertEquals(1, this.clientListener.getListMsg().size());
+               assertTrue(this.clientListener.getListMsg().get(0) instanceof BGPOpenMessage);
+               final List<BGPParameter> tlvs = Lists.newArrayList();
+               tlvs.add(new MultiprotocolCapability(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast)));
+               this.clientListener.sendMessage(new BGPOpenMessage(new ASNumber(30), (short) 3, null, tlvs));
+               assertEquals(2, this.clientListener.getListMsg().size());
+               assertTrue(this.clientListener.getListMsg().get(1) instanceof BGPKeepAliveMessage);
+               this.clientListener.sendMessage(new BGPKeepAliveMessage());
+               synchronized (this.speakerListener) {
+                       while (!this.speakerListener.up)
+                               try {
+                                       this.speakerListener.wait();
+                                       fail("Exception should have occured.");
+                               } catch (final InterruptedException e) {
+                                       e.printStackTrace();
+                               }
+               }
+               assertTrue(this.speakerListener.up);
+               assertEquals(this.speakerListener.types,
+                               Sets.newHashSet(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast)));
+               Thread.sleep(1 * 1000);
+               assertEquals(3, this.clientListener.getListMsg().size());
+               assertTrue(this.clientListener.getListMsg().get(2) instanceof BGPKeepAliveMessage); // test of keepalive timer
+               this.clientListener.sendMessage(new BGPOpenMessage(new ASNumber(30), (short) 3, null, null));
+               assertEquals(4, this.clientListener.getListMsg().size());
+               assertTrue(this.clientListener.getListMsg().get(3) instanceof BGPNotificationMessage);
+               final BGPMessage m = this.clientListener.getListMsg().get(3);
+               assertEquals(BGPError.FSM_ERROR, ((BGPNotificationMessage) m).getError());
+       }
+
+       @Test
+       public void testNotAccChars() throws InterruptedException {
+               this.speaker.startSession();
+               assertEquals(1, this.clientListener.getListMsg().size());
+               assertTrue(this.clientListener.getListMsg().get(0) instanceof BGPOpenMessage);
+               this.clientListener.sendMessage(new BGPOpenMessage(new ASNumber(30), (short) 1, null, null));
+               assertEquals(2, this.clientListener.getListMsg().size());
+               assertTrue(this.clientListener.getListMsg().get(1) instanceof BGPKeepAliveMessage);
+               assertFalse(this.speakerListener.up);
+               Thread.sleep(BGPSessionImpl.HOLD_TIMER_VALUE * 1000);
+               Thread.sleep(100);
+               final BGPMessage m = this.clientListener.getListMsg().get(this.clientListener.getListMsg().size() - 1);
+               assertEquals(BGPError.HOLD_TIMER_EXPIRED, ((BGPNotificationMessage) m).getError());
+       }
+
+       @Test
+       @Ignore
+       // long duration
+       public void testNoOpen() throws InterruptedException {
+               this.speaker.startSession();
+               assertEquals(1, this.clientListener.getListMsg().size());
+               assertTrue(this.clientListener.getListMsg().get(0) instanceof BGPOpenMessage);
+               Thread.sleep(BGPSessionImpl.HOLD_TIMER_VALUE * 1000);
+               Thread.sleep(100);
+               final BGPMessage m = this.clientListener.getListMsg().get(this.clientListener.getListMsg().size() - 1);
+               assertEquals(BGPError.HOLD_TIMER_EXPIRED, ((BGPNotificationMessage) m).getError());
+       }
+
+       @Test
+       public void sendNotification() {
+               this.speaker.startSession();
+               this.clientListener.sendMessage(new BGPOpenMessage(new ASNumber(30), (short) 3, null, null));
+               this.clientListener.sendMessage(new BGPKeepAliveMessage());
+               synchronized (this.speakerListener) {
+                       while (!this.speakerListener.up)
+                               try {
+                                       this.speakerListener.wait();
+                                       fail("Exception should have occured.");
+                               } catch (final InterruptedException e) {
+                                       e.printStackTrace();
+                               }
+               }
+               assertTrue(this.speakerListener.up);
+               this.clientListener.sendMessage(new BGPNotificationMessage(BGPError.CEASE));
+               assertFalse(this.speakerListener.up);
+       }
+
+       @Test
+       public void complementaryTests() {
+               assertEquals(4096, this.speaker.maximumMessageSize());
+
+               assertNotNull(this.speaker.getStream());
+       }
+
+       @After
+       public void tearDown() {
+               this.speaker.close();
+       }
+}
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/InputStreamTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/InputStreamTest.java
new file mode 100644 (file)
index 0000000..cc95d0e
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.rib.impl.BGPInputStream;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+
+public class InputStreamTest {
+
+       @Mock
+       PipedInputStream pis;
+
+       @Mock
+       BGPMessageFactory mf;
+
+       @Mock
+       BGPMessageHeader h;
+
+       BGPInputStream is;
+
+       @Before
+       public void setUp() throws IOException {
+               MockitoAnnotations.initMocks(this);
+               this.is = (BGPInputStream) BGPInputStream.FACTORY.getProtocolInputStream(this.pis, this.mf);
+       }
+
+       @Test
+       public void testHeaderNotAvailable() throws IOException {
+               doReturn(BGPMessageHeader.COMMON_HEADER_LENGTH - 4).when(this.pis).available();
+               doReturn(-1).when(this.pis).read((byte[]) any());
+               assertFalse(this.is.isMessageAvailable());
+               assertFalse(this.is.header.isParsed());
+       }
+
+       @Test
+       public void testHeaderAvailable() throws IOException {
+               doReturn(BGPMessageHeader.COMMON_HEADER_LENGTH).when(this.pis).available();
+               doReturn(5).when(this.pis).read((byte[]) any());
+               assertTrue(this.is.isMessageAvailable());
+               assertTrue(this.is.header.isParsed());
+       }
+
+       @Test
+       public void testGetMessage() throws IOException, DeserializerException, DocumentedException {
+               doReturn(BGPMessageHeader.COMMON_HEADER_LENGTH).when(this.pis).available();
+               doReturn(5).when(this.pis).read((byte[]) any());
+               doReturn("").when(this.h).toString();
+               this.is.header = this.h;
+               doNothing().when(this.h).setParsed();
+               doReturn(true).when(this.h).isParsed();
+               doReturn(100).when(this.h).getLength();
+               doReturn(mock(BGPMessage.class)).when(this.mf).parse((byte[]) any(), any(BGPMessageHeader.class));
+               assertTrue(this.is.getMessage() instanceof BGPMessage);
+       }
+}
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/MockDispatcher.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/MockDispatcher.java
new file mode 100644 (file)
index 0000000..e50da39
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.IOException;
+
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.SessionParent;
+
+public class MockDispatcher implements SessionParent {
+
+       @Override
+       public void onSessionClosed(final ProtocolSession session) {
+
+       }
+
+       @Override
+       public void checkOutputBuffer(final ProtocolSession session) {
+
+       }
+
+       @Override
+       public void close() throws IOException {
+       }
+}
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserTest.java
new file mode 100644 (file)
index 0000000..7b27097
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.GracefulCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.util.ByteArray;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class ParserTest {
+
+       public static final byte[] openBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                       (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                       (byte) 0xff, (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4,
+                       (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
+
+       public static final byte[] keepAliveBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                       (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                       (byte) 0xff, (byte) 0x00, (byte) 0x13, (byte) 0x04 };
+
+       public static final byte[] notificationBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                       (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                       (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 };
+
+       final BGPMessageHeader header = new BGPMessageHeader();
+
+       final BGPMessageParser factory = new BGPMessageFactory();
+
+       @Test
+       public void testHeaderErrors() {
+               final byte[] wrong = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0x00 };
+               try {
+                       this.header.fromBytes(wrong);
+                       fail("Exception should have occcured.");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= "
+                                       + BGPMessageHeader.COMMON_HEADER_LENGTH + ".", e.getMessage());
+                       return;
+               }
+               fail();
+       }
+
+       @Test
+       public void testBadMsgType() throws DeserializerException {
+               byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+                               (byte) 0x13, (byte) 0x08 };
+               final BGPMessageHeader h = this.header.fromBytes(bytes);
+               bytes = ByteArray.cutBytes(bytes, 19);
+               try {
+                       this.factory.parse(bytes, h);
+                       fail("Exception should have occured.");
+               } catch (final DocumentedException e) {
+                       assertEquals("Unhandled message type " + h.getType(), e.getMessage());
+                       assertEquals(BGPError.BAD_MSG_TYPE, ((BGPDocumentedException) e).getError());
+                       return;
+               }
+               fail();
+       }
+
+       @Test
+       public void testKeepAliveMsg() throws DeserializerException, DocumentedException {
+               final BGPMessage keepAlive = new BGPKeepAliveMessage();
+               byte[] bytes = this.factory.put(keepAlive);
+               assertArrayEquals(keepAliveBMsg, bytes);
+
+               final BGPMessageHeader h = this.header.fromBytes(keepAliveBMsg);
+               bytes = ByteArray.cutBytes(bytes, 19);
+               final BGPMessage m = this.factory.parse(bytes, h);
+
+               assertTrue(m instanceof BGPKeepAliveMessage);
+       }
+
+       @Test
+       public void testBadKeepAliveMsg() throws DeserializerException {
+               byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+                               (byte) 0x14, (byte) 0x04, (byte) 0x05 };
+
+               final BGPMessageHeader h = this.header.fromBytes(bytes);
+               bytes = ByteArray.cutBytes(bytes, 19);
+               try {
+                       this.factory.parse(bytes, h);
+                       fail("Exception should have occured.");
+               } catch (final DocumentedException e) {
+                       assertThat(e.getMessage(), containsString("Message length field not within valid range."));
+                       assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
+                       return;
+               }
+               fail();
+       }
+
+       @Test
+       public void testOpenMessage() throws UnknownHostException, DeserializerException, DocumentedException {
+               final BGPMessage open = new BGPOpenMessage(new ASNumber(100), (short) 180, new IPv4Address(InetAddress.getByName("20.20.20.20")), null);
+               byte[] bytes = this.factory.put(open);
+               assertArrayEquals(openBMsg, bytes);
+
+               final BGPMessageHeader h = this.header.fromBytes(openBMsg);
+               bytes = ByteArray.cutBytes(bytes, 19);
+               final BGPMessage m = this.factory.parse(bytes, h);
+
+               assertTrue(m instanceof BGPOpenMessage);
+               assertEquals(new ASNumber(100), ((BGPOpenMessage) m).getMyAS());
+               assertEquals((short) 180, ((BGPOpenMessage) m).getHoldTime());
+               assertEquals(new IPv4Address(InetAddress.getByName("20.20.20.20")), ((BGPOpenMessage) m).getBgpId());
+               assertTrue(((BGPOpenMessage) m).getOptParams().isEmpty());
+       }
+
+       @Test
+       public void testBadHoldTimeError() throws DeserializerException {
+               byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+                               (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14, (byte) 0x14,
+                               (byte) 0x14, (byte) 0x14, (byte) 0x00 };
+
+               final BGPMessageHeader h = this.header.fromBytes(bMsg);
+               bMsg = ByteArray.cutBytes(bMsg, 19);
+               try {
+                       this.factory.parse(bMsg, h);
+                       fail("Exception should have occured.");
+               } catch (final DocumentedException e) {
+                       assertEquals("Hold time value not acceptable.", e.getMessage());
+                       assertEquals(BGPError.HOLD_TIME_NOT_ACC, ((BGPDocumentedException) e).getError());
+                       return;
+               }
+               fail();
+       }
+
+       @Test
+       public void testBadMsgLength() throws DeserializerException {
+               byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+                               (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff };
+
+               final BGPMessageHeader h = this.header.fromBytes(bMsg);
+               bMsg = ByteArray.cutBytes(bMsg, 19);
+               try {
+                       this.factory.parse(bMsg, h);
+                       fail("Exception should have occured.");
+               } catch (final DocumentedException e) {
+                       assertEquals("Open message too small.", e.getMessage());
+                       assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
+               }
+       }
+
+       @Test
+       public void testBadVersion() throws DeserializerException {
+               byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+                               (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14, (byte) 0x14,
+                               (byte) 0x14, (byte) 0x14, (byte) 0x00 };
+
+               final BGPMessageHeader h = this.header.fromBytes(bMsg);
+               bMsg = ByteArray.cutBytes(bMsg, 19);
+               try {
+                       this.factory.parse(bMsg, h);
+                       fail("Exception should have occured.");
+               } catch (final DocumentedException e) {
+                       assertEquals("BGP Protocol version 8 not supported.", e.getMessage());
+                       assertEquals(BGPError.VERSION_NOT_SUPPORTED, ((BGPDocumentedException) e).getError());
+                       return;
+               }
+               fail();
+       }
+
+       @Test
+       public void testNotificationMsg() throws DeserializerException, DocumentedException {
+               BGPMessage notMsg = new BGPNotificationMessage(BGPError.OPT_PARAM_NOT_SUPPORTED, new byte[] { 4, 9 });
+               byte[] bytes = this.factory.put(notMsg);
+               assertArrayEquals(notificationBMsg, bytes);
+
+               BGPMessageHeader h = this.header.fromBytes(notificationBMsg);
+               bytes = ByteArray.cutBytes(bytes, 19);
+               BGPMessage m = this.factory.parse(bytes, h);
+
+               assertTrue(m instanceof BGPNotificationMessage);
+               assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, ((BGPNotificationMessage) m).getError());
+               assertArrayEquals(new byte[] { 4, 9 }, ((BGPNotificationMessage) m).getData());
+
+               notMsg = new BGPNotificationMessage(BGPError.CONNECTION_NOT_SYNC);
+               bytes = this.factory.put(notMsg);
+
+               h = this.header.fromBytes(bytes);
+               bytes = ByteArray.cutBytes(bytes, 19);
+               m = this.factory.parse(bytes, h);
+
+               assertTrue(m instanceof BGPNotificationMessage);
+               assertEquals(BGPError.CONNECTION_NOT_SYNC, ((BGPNotificationMessage) m).getError());
+               assertNull(((BGPNotificationMessage) m).getData());
+       }
+
+       @Test
+       public void testWrongLength() throws DeserializerException {
+               byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+                               (byte) 0x14, (byte) 0x03, (byte) 0x02 };
+
+               final BGPMessageHeader h = this.header.fromBytes(bMsg);
+               bMsg = ByteArray.cutBytes(bMsg, 19);
+               try {
+                       this.factory.parse(bMsg, h);
+                       fail("Exception should have occured.");
+               } catch (final DocumentedException e) {
+                       assertEquals("Notification message too small.", e.getMessage());
+                       assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
+                       return;
+               }
+               fail();
+       }
+
+       @Test
+       public void testUnrecognizedError() throws DeserializerException, DocumentedException {
+               byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                               (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+                               (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa };
+
+               final BGPMessageHeader h = this.header.fromBytes(bMsg);
+               bMsg = ByteArray.cutBytes(bMsg, 19);
+               try {
+                       this.factory.parse(bMsg, h);
+                       fail("Exception should have occured.");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage());
+                       return;
+               }
+               fail();
+       }
+
+       @Test
+       public void testTLVParser() throws UnknownHostException {
+
+               final BGPTableType t1 = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+               final BGPTableType t2 = new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Unicast);
+
+               final List<BGPParameter> tlvs = Lists.newArrayList();
+               tlvs.add(new MultiprotocolCapability(t1));
+               tlvs.add(new MultiprotocolCapability(t2));
+               final Map<BGPTableType, Boolean> tableTypes = Maps.newHashMap();
+               tableTypes.put(t1, true);
+               tableTypes.put(t2, true);
+               tlvs.add(new GracefulCapability(true, 0, tableTypes));
+               final BGPOpenMessage open = new BGPOpenMessage(new ASNumber(72), (short) 180, new IPv4Address(InetAddress.getByName("172.20.160.170")), tlvs);
+
+               // System.out.println(Arrays.toString(this.factory.put(open)));
+
+               this.factory.put(open);
+
+               // assertArrayEquals(openWithCpblt, bytes);
+       }
+}
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SimpleSessionListener.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SimpleSessionListener.java
new file mode 100644 (file)
index 0000000..30b7cbd
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Listener for the client.
+ */
+public class SimpleSessionListener extends BGPSessionListener {
+
+       private final List<BGPMessage> listMsg = Lists.newArrayList();
+
+       private BGPSessionImpl session = null;
+
+       public boolean up = false;
+
+       private static final Logger logger = LoggerFactory.getLogger(SimpleSessionListener.class);
+
+       public boolean down = false;
+
+       public SimpleSessionListener() {
+       }
+
+       public void sendMessage(final BGPMessage msg) {
+               this.session.handleMessage(msg);
+       }
+
+       public List<BGPMessage> getListMsg() {
+               return this.listMsg;
+       }
+
+       public void addSession(final BGPSessionImpl l) {
+               this.session = l;
+       }
+
+       @Override
+       public void onMessage(final BGPMessage message) {
+               this.listMsg.add(message);
+               logger.debug("Message received:" + message);
+       }
+
+       @Override
+       public void onSessionUp(final Set<BGPTableType> remote) {
+               logger.debug("Session Up");
+               this.up = true;
+               this.notifyAll();
+       }
+
+       @Override
+       public void onSessionDown(final BGPSession session, final Exception e) {
+               logger.debug("Session Down", e);
+               this.down = true;
+       }
+
+       @Override
+       public void onSessionTerminated(final BGPError cause) {
+               logger.debug("Session terminated. Cause : " + cause.toString());
+       }
+}
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SpeakerSessionListener.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SpeakerSessionListener.java
new file mode 100644 (file)
index 0000000..5517414
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Listener for the BGP Speaker.
+ */
+public class SpeakerSessionListener extends BGPSessionListener {
+
+       public List<BGPMessage> messages = Lists.newArrayList();
+
+       public boolean up = false;
+
+       public Set<BGPTableType> types;
+
+       private static final Logger logger = LoggerFactory.getLogger(SpeakerSessionListener.class);
+
+       public SpeakerSessionListener() {
+       }
+
+       @Override
+       public void onMessage(final BGPMessage message) {
+               logger.debug("Received message: " + message.getClass() + " " + message);
+               this.messages.add(message);
+       }
+
+       @Override
+       public synchronized void onSessionUp(final Set<BGPTableType> remote) {
+               logger.debug("Session up.");
+               this.up = true;
+               this.types = remote;
+               this.notifyAll();
+       }
+
+       @Override
+       public void onSessionDown(final BGPSession session, final Exception e) {
+               logger.debug("Session down.");
+               this.up = false;
+       }
+
+       @Override
+       public void onSessionTerminated(final BGPError cause) {
+               logger.debug("Session terminated. Cause : " + cause.toString());
+               this.up = false;
+       }
+}
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SpeakerSessionMock.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SpeakerSessionMock.java
new file mode 100644 (file)
index 0000000..b322d5c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Timer;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.rib.impl.BGPConnectionImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionProposalCheckerImpl;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * Mock of the BGP speakers session.
+ */
+public class SpeakerSessionMock extends BGPSessionImpl {
+
+       private final BGPSessionListener client;
+
+       SpeakerSessionMock(final BGPSessionListener listener, final BGPSessionListener client) {
+               super(new MockDispatcher(), new Timer(), new BGPConnectionImpl(null, listener, new BGPSessionPreferences(new ASNumber(30), (short) 15, null, null), new BGPSessionProposalCheckerImpl()), 3, null);
+               this.client = client;
+       }
+
+       @Override
+       public void sendMessage(final BGPMessage msg) {
+               this.lastMessageSentAt = System.nanoTime();
+               this.client.onMessage(msg);
+       }
+}
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SynchronizationTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SynchronizationTest.java
new file mode 100644 (file)
index 0000000..6e5abf2
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.util.Collections;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.parser.BGPLink;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.parser.impl.BGPUpdateMessageImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSynchronization;
+import org.opendaylight.protocol.bgp.rib.impl.BGPUpdateSynchronizedImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv6;
+import com.google.common.collect.Sets;
+
+public class SynchronizationTest {
+
+       private BGPSynchronization bs;
+
+       private SimpleSessionListener listener;
+
+       private BGPUpdateMessage ipv4m;
+
+       private BGPUpdateMessage ipv6m;
+
+       private BGPUpdateMessage lsm;
+
+       @Before
+       public void setUp() {
+               this.listener = new SimpleSessionListener();
+               final BGPIPv4RouteImpl i4 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("1.1.1.1/32"), new BaseBGPObjectState(null, null), null);
+               this.ipv4m = new BGPUpdateMessageImpl(Sets.<BGPObject> newHashSet(i4), Collections.EMPTY_SET);
+               final BGPIPv6RouteImpl i6 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("::1/32"), new BaseBGPObjectState(null, null), null);
+               this.ipv6m = new BGPUpdateMessageImpl(Sets.<BGPObject> newHashSet(i6), Collections.EMPTY_SET);
+               this.lsm = new BGPUpdateMessageImpl(Sets.<BGPObject> newHashSet(mock(BGPLink.class)), Collections.EMPTY_SET);
+               this.bs = new BGPSynchronization(this.listener);
+               this.bs.addTableTypes(Sets.newHashSet(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast),
+                               new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Linkstate)));
+       }
+
+       @Test
+       public void testSynchronize() {
+               // simulate sync
+               this.bs.updReceived(this.ipv6m);
+
+               this.bs.updReceived(this.ipv4m);
+               this.bs.updReceived(this.lsm);
+               this.bs.kaReceived(); // nothing yet
+               this.bs.updReceived(this.ipv4m);
+               this.bs.kaReceived(); // linkstate
+               assertEquals(1, this.listener.getListMsg().size());
+               this.bs.kaReceived(); // ipv4 sync
+               assertEquals(2, this.listener.getListMsg().size());
+               assertEquals(BGPAddressFamily.IPv4,
+                               ((BGPUpdateSynchronizedImpl) this.listener.getListMsg().get(1)).getTableType().getAddressFamily());
+       }
+}
diff --git a/bgp/rib-mock/.gitignore b/bgp/rib-mock/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/bgp/rib-mock/.project b/bgp/rib-mock/.project
new file mode 100644 (file)
index 0000000..ea9e1de
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>bgp-update-mock</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bgp/rib-mock/pom.xml b/bgp/rib-mock/pom.xml
new file mode 100644 (file)
index 0000000..5bcaa27
--- /dev/null
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>bgp-parent</artifactId>
+               <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-rib-mock</artifactId>
+       <description>BGP Update Mock Implementation</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-rib-impl</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>util</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-parser-impl</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>mockito-configuration</artifactId>
+                       <version>1.0</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-api</artifactId>
+                       <version>${slf4j.version}</version>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.bgp.rib.mock,
+                                               </Export-Package>
+                                               <Import-Package>
+                                                       org.opendaylight.protocol.concepts,
+                                                       org.opendaylight.protocol.framework,
+                                                       org.opendaylight.protocol.bgp.linkstate,
+                                                       com.google.common.*,
+                                                       javax.annotation,
+                                                       javax.management,
+                                                       org.apache.commons.codec,
+                                                       org.apache.commons.codec.binary,
+                                                       org.apache.commons.lang,
+                                                       org.opendaylight.protocol.bgp.concepts,
+                                                       org.opendaylight.protocol.bgp.parser,
+                            org.opendaylight.protocol.bgp.parser.impl,
+                                                       org.opendaylight.protocol.bgp.parser.message,
+                            org.opendaylight.protocol.bgp.parser.parameter,
+                            org.opendaylight.protocol.bgp.rib.impl,
+                            org.opendaylight.protocol.util,
+                                                       org.slf4j,
+                                               </Import-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-jar-plugin</artifactId>
+                               <version>2.4</version>
+                               <executions>
+                                       <execution>
+                                               <phase>package</phase>
+                                               <goals>
+                                                       <goal>test-jar</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>BGP-UPDATE-MOCK Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/bgp/rib-mock/src/main/java/org/opendaylight/protocol/bgp/rib/mock/BGPMock.java b/bgp/rib-mock/src/main/java/org/opendaylight/protocol/bgp/rib/mock/BGPMock.java
new file mode 100644 (file)
index 0000000..7b2aaea
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.mock;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.rib.impl.BGP;
+import org.opendaylight.protocol.util.ByteArray;
+
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import com.google.common.collect.Lists;
+import com.google.common.eventbus.EventBus;
+
+/**
+ * 
+ * Mock implementation of {@link BGP}.
+ * 
+ */
+@ThreadSafe
+public final class BGPMock implements BGP, Closeable {
+       static final BGPMessage connectionLostMagicMessage = new BGPNotificationMessage(BGPError.CEASE);
+
+       @GuardedBy("this")
+       private final List<byte[]> allPreviousByteMessages;
+       private final List<BGPMessage> allPreviousBGPMessages;
+       private final EventBus eventBus;
+       @GuardedBy("this")
+       private final List<EventBusRegistration> openRegistrations = Lists.newLinkedList();
+
+       public BGPMock(final EventBus eventBus, final List<byte[]> bgpMessages) {
+               this.allPreviousByteMessages = Lists.newLinkedList(bgpMessages);
+               this.eventBus = eventBus;
+               this.allPreviousBGPMessages = this.parsePrevious(this.allPreviousByteMessages);
+       }
+
+       private List<BGPMessage> parsePrevious(final List<byte[]> msgs) {
+               final List<BGPMessage> messages = Lists.newArrayList();
+               final BGPMessageParser parser = new BGPMessageFactory();
+               try {
+                       for (final byte[] b : msgs) {
+                               final BGPMessageHeader header = new BGPMessageHeader();
+                               header.fromBytes(ByteArray.subByte(b, 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+                               final byte[] body = ByteArray.cutBytes(b, BGPMessageHeader.COMMON_HEADER_LENGTH);
+
+                               messages.add(parser.parse(body, header));
+                       }
+                       parser.close();
+               } catch (final IOException e) {
+                       e.printStackTrace();
+               } catch (final DeserializerException e) {
+                       e.printStackTrace();
+               } catch (final DocumentedException e) {
+                       e.printStackTrace();
+               }
+               return messages;
+       }
+
+       /**
+        * @param listener BGPListener
+        * @return ListenerRegistration
+        */
+       @Override
+       public synchronized ListenerRegistration<BGPSessionListener> registerUpdateListener(final BGPSessionListener listener) {
+               return EventBusRegistration.createAndRegister(this.eventBus, listener, this.allPreviousBGPMessages);
+       }
+
+       public synchronized void insertConnectionLostEvent() {
+               this.insertMessage(connectionLostMagicMessage);
+       }
+
+       public synchronized void insertMessages(final List<BGPMessage> messages) {
+               for (final BGPMessage message : messages)
+                       this.insertMessage(message);
+       }
+
+       private synchronized void insertMessage(final BGPMessage message) {
+               this.allPreviousBGPMessages.add(message);
+               this.eventBus.post(message);
+       }
+
+       @Override
+       public synchronized void close() {
+               // unregister all EventBusRegistration instances
+               for (final EventBusRegistration registration : this.openRegistrations) {
+                       registration.close();
+               }
+               this.openRegistrations.clear();
+       }
+
+       public boolean isMessageListSame(final List<byte[]> newMessages) {
+               if (this.allPreviousBGPMessages.size() != newMessages.size())
+                       return false;
+               final Iterator<byte[]> i1 = this.allPreviousByteMessages.iterator();
+               final Iterator<byte[]> i2 = this.allPreviousByteMessages.iterator();
+               for (int i = 0; i < this.allPreviousBGPMessages.size(); i++) {
+                       if (!Arrays.equals(i1.next(), i2.next()))
+                               return false;
+               }
+               return true;
+       }
+
+       public EventBus getEventBus() {
+               return this.eventBus;
+       }
+}
diff --git a/bgp/rib-mock/src/main/java/org/opendaylight/protocol/bgp/rib/mock/EventBusRegistration.java b/bgp/rib-mock/src/main/java/org/opendaylight/protocol/bgp/rib/mock/EventBusRegistration.java
new file mode 100644 (file)
index 0000000..5393270
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.mock;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+import com.google.common.collect.Sets;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
+/**
+ * This class has @Subscribe annotated methods which receive events from {@link EventBus} . Events are produced by
+ * {@link BGPMock}, and each instance notifies exactly one {@link BGPSessionListener}.
+ */
+class EventBusRegistration implements ListenerRegistration<BGPSessionListener> {
+       private final EventBus eventBus;
+       private final BGPSessionListener listener;
+       @GuardedBy("this")
+       private boolean closed = false;
+
+       public static EventBusRegistration createAndRegister(final EventBus eventBus, final BGPSessionListener listener,
+                       final List<BGPMessage> allPreviousMessages) {
+               final EventBusRegistration instance = new EventBusRegistration(eventBus, listener, allPreviousMessages);
+               eventBus.register(instance);
+               return instance;
+       }
+
+       private EventBusRegistration(final EventBus eventBus, final BGPSessionListener listener, final List<BGPMessage> allPreviousMessages) {
+               this.eventBus = eventBus;
+               this.listener = listener;
+               for (final BGPMessage message : allPreviousMessages)
+                       sendMessage(listener, message);
+       }
+
+       @Subscribe
+       public void onMessage(final BGPMessage message) {
+               sendMessage(this.listener, message);
+       }
+
+       @Override
+       public synchronized void close() {
+               if (this.closed)
+                       return;
+               this.eventBus.unregister(this);
+               this.closed = true;
+       }
+
+       private static void sendMessage(final BGPSessionListener listener, final BGPMessage message) {
+               if (BGPMock.connectionLostMagicMessage.equals(message)) {
+                       listener.onSessionTerminated(null);
+               } else if (message instanceof BGPOpenMessage) {
+                       final Set<BGPTableType> tts = Sets.newHashSet();
+                       for (final BGPParameter param : ((BGPOpenMessage) message).getOptParams()) {
+                               if (param instanceof MultiprotocolCapability) {
+                                       tts.add(((MultiprotocolCapability) param).getTableType());
+                               }
+                       }
+                       listener.onSessionUp(tts);
+               } else if (message instanceof BGPKeepAliveMessage) {
+                       // do nothing
+               } else {
+                       listener.onMessage(message);
+               }
+       }
+
+       @Override
+       public BGPSessionListener getListener() {
+               return this.listener;
+       }
+}
diff --git a/bgp/rib-mock/src/site/apt/index.apt.vm b/bgp/rib-mock/src/site/apt/index.apt.vm
new file mode 100644 (file)
index 0000000..240ca24
--- /dev/null
@@ -0,0 +1,6 @@
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
diff --git a/bgp/rib-mock/src/site/site.xml b/bgp/rib-mock/src/site/site.xml
new file mode 100644 (file)
index 0000000..e468b3b
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+  <body>
+    <head>${project.artifactId}</head>
+    <links>
+      <item name="${project.artifactId}" href="index.html"/>
+    </links>
+
+    <menu ref="parent"/>
+
+    <menu ref="reports"/>
+
+    
+  </body>
+</project>
+
diff --git a/bgp/rib-mock/src/test/java/org/opendaylight/protocol/bgp/rib/mock/BGPListenerMock.java b/bgp/rib-mock/src/test/java/org/opendaylight/protocol/bgp/rib/mock/BGPListenerMock.java
new file mode 100644 (file)
index 0000000..86331cf
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.mock;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+
+
+/**
+ * Mock implementation of {@link BGPListener} for testing purposes.
+ */
+final class BGPListenerMock extends BGPSessionListener {
+       private final List<BGPMessage> buffer = Collections.synchronizedList(new ArrayList<BGPMessage>());
+       private boolean connected = false;
+
+       protected List<BGPMessage> getBuffer() {
+               return this.buffer;
+       }
+
+       protected boolean isConnected() {
+               return this.connected;
+       }
+
+       @Override
+       public void onMessage(final BGPMessage message) {
+               this.buffer.add(message);
+       }
+
+       @Override
+       public void onSessionUp(final Set<BGPTableType> remoteParams) {
+               this.connected = true;
+       }
+
+       @Override
+       public void onSessionDown(final BGPSession session, final Exception e) {
+               this.connected = false;
+       }
+
+       @Override
+       public void onSessionTerminated(final BGPError cause) {
+               this.connected = false;
+       }
+}
diff --git a/bgp/rib-mock/src/test/resources/BgpMessages b/bgp/rib-mock/src/test/resources/BgpMessages
new file mode 100644 (file)
index 0000000..c923b86
Binary files /dev/null and b/bgp/rib-mock/src/test/resources/BgpMessages differ
diff --git a/bgp/rib-mock/src/test/resources/OpenMessage b/bgp/rib-mock/src/test/resources/OpenMessage
new file mode 100644 (file)
index 0000000..9975c32
Binary files /dev/null and b/bgp/rib-mock/src/test/resources/OpenMessage differ
diff --git a/bgp/rib-mock/src/test/resources/bgp_hex.txt b/bgp/rib-mock/src/test/resources/bgp_hex.txt
new file mode 100644 (file)
index 0000000..f0920be
--- /dev/null
@@ -0,0 +1,86 @@
+Receive BGP Update message for 0x804b6a0: Length = 61
+   
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 3d 01 04 00 14 00 b4    14 14 14 14 20 02 06 01    
+04 00 01 00 01 02 06 01    04 00 1b 00 01 02 02 80    
+00 02 02 02 00 02 06 41    04 00 00 00 14 
+
+Receive BGP Update message for 0x804b6a0: Length = 151
+   
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 40 02 00 00 00 1f 40    01 01 00 40 02 0a 02 02    
+00 00 00 64 00 00 00 46    40 03 04 0a 01 01 0a 40    
+05 04 00 00 00 64 20 46    01 02 02 20 46 01 01 01    
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 40 02 00 00 00 1f 40    01 01 00 40 02 0a 02 02    
+00 00 00 64 00 00 00 5a    40 03 04 0a 01 01 0a 40    
+05 04 00 00 00 64 20 5a    01 02 02 20 5a 01 01 01    
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 17 02 00 00 00 00 
+
+Receive BGP Update message for 0x804b6a0: Length = 1021
+   
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 70 02 00 00 00 59 90    0e 00 37 00 1b 01 04 0a    
+01 01 0a 00 00 01 00 2a    01 00 00 00 01 00 00 13    
+01 02 00 04 64 00 00 00    01 06 00 07 00 00 00 00    
+00 01 00 01 01 00 0b 01    06 00 07 00 00 00 00 00    
+02 03 40 01 01 00 40 02    06 02 01 00 00 00 64 40    
+05 04 00 00 00 64 80 ff    07 01 13 00 03 15 00 00    
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+01 28 02 00 00 01 11 90    0e 00 ef 00 1b 01 04 0a    
+01 01 0a 00 00 01 00 2a    01 00 00 00 01 00 00 13    
+01 02 00 04 64 00 00 00    01 06 00 07 00 00 00 00    
+00 10 00 01 01 00 0b 01    06 00 07 00 00 00 00 00    
+10 03 00 01 00 2a 01 00    00 00 01 00 00 13 01 02    
+00 04 64 00 00 00 01 06    00 07 00 00 00 00 00 10    
+00 01 01 00 0b 01 06 00    07 00 00 00 00 00 10 01    
+00 01 00 2a 01 00 00 00    01 00 00 13 01 02 00 04    
+64 00 00 00 01 06 00 07    00 00 00 00 00 02 00 01    
+01 00 0b 01 06 00 07 00    00 00 00 00 10 01 00 01    
+00 2a 01 00 00 00 01 00    00 13 01 02 00 04 64 00    
+00 00 01 06 00 07 00 00    00 00 00 02 00 01 01 00    
+0b 01 06 00 07 00 00 00    00 00 02 03 00 01 00 2a    
+01 00 00 00 01 00 00 13    01 02 00 04 64 00 00 00    
+01 06 00 07 00 00 00 00    00 01 00 01 01 00 0b 01    
+06 00 07 00 00 00 00 00    10 03 40 01 01 00 40 02    
+06 02 01 00 00 00 64 40    05 04 00 00 00 64 80 ff    
+07 01 13 00 03 0a 00 00    ff ff ff ff ff ff ff ff    
+ff ff ff ff ff ff ff ff    01 56 02 00 00 01 3f 90    
+0e 01 1d 00 1b 01 04 0a    01 01 0a 00 00 01 00 2a    
+01 00 00 00 01 00 00 13    01 02 00 04 64 00 00 00    
+01 06 00 07 00 00 00 00    00 10 03 01 01 00 0b 01    
+06 00 07 00 00 00 00 00    10 00 00 01 00 2a 01 00    
+00 00 01 00 00 13 01 02    00 04 64 00 00 00 01 06    
+00 07 00 00 00 00 00 10    03 01 01 00 0b 01 06 00    
+07 00 00 00 00 00 01 00    00 01 00 2a 01 00 00 00    
+01 00 00 13 01 02 00 04    64 00 00 00 01 06 00 07    
+00 00 00 00 00 10 01 01    01 00 0b 01 06 00 07 00    
+00 00 00 00 10 00 00 01    00 2a 01 00 00 00 01 00    
+00 13 01 02 00 04 64 00    00 00 01 06 00 07 00 00    
+00 00 00 10 01 01 01 00    0b 01 06 00 07 00 00 00    
+00 00 02 00 00 01 00 2a    01 00 00 00 01 00 00 13    
+01 02 00 04 64 00 00 00    01 06 00 07 00 00 00 00    
+00 02 03 01 01 00 0b 01    06 00 07 00 00 00 00 00    
+02 00 00 01 00 2a 01 00    00 00 01 00 00 13 01 02    
+00 04 64 00 00 00 01 06    00 07 00 00 00 00 00 02    
+03 01 01 00 0b 01 06 00    07 00 00 00 00 00 01 00    
+40 01 01 00 40 02 06 02    01 00 00 00 64 40 05 04    
+00 00 00 64 80 ff 07 01    13 00 03 00 00 00 ff ff    
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff 00 f2    
+02 00 00 00 db 90 0e 00    c3 00 1b 01 04 0a 01 01    
+0a 00 00 02 00 1b 01 00    00 00 01 00 00 13 01 02    
+00 04 64 00 00 00 01 06    00 07 00 00 00 00 00 10    
+03 00 02 00 1b 01 00 00    00 01 00 00 13 01 02 00    
+04 64 00 00 00 01 06 00    07 00 00 00 00 00 10 01    
+00 02 00 1b 01 00 00 00    01 00 00 13 01 02 00 04    
+64 00 00 00 01 06 00 07    00 00 00 00 00 10 00 00    
+02 00 1b 01 00 00 00 01    00 00 13 01 02 00 04 64    
+00 00 00 01 06 00 07 00    00 00 00 00 02 03 00 02    
+00 1b 01 00 00 00 01 00    00 13 01 02 00 04 64 00    
+00 00 01 06 00 07 00 00    00 00 00 02 00 00 02 00    
+1b 01 00 00 00 01 00 00    13 01 02 00 04 64 00 00    
+00 01 06 00 07 00 00 00    00 00 01 00 40 01 01 00    
+40 02 06 02 01 00 00 00    64 40 05 04 00 00 00 64    
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 1d 02 00 00 00 06 80    0f 03 00 1b 01 
diff --git a/bgp/testtool/.gitignore b/bgp/testtool/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/bgp/testtool/.project b/bgp/testtool/.project
new file mode 100644 (file)
index 0000000..0d82a3d
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>bgp-testing-tool</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bgp/testtool/pom.xml b/bgp/testtool/pom.xml
new file mode 100644 (file)
index 0000000..b55ac0b
--- /dev/null
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+        <groupId>org.opendaylight.protocol</groupId>
+        <artifactId>bgp-parent</artifactId>
+        <version>1.0</version>
+    </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-testtool</artifactId>
+       <description>BGP Interop Testing Tool</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+        <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>framework</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-parser-impl</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-rib-impl</artifactId>
+                       <version>1.0</version>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.bgp.testtool
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-shade-plugin</artifactId>
+                               <version>1.7.1</version>
+                               <configuration>
+                               </configuration>
+                               <executions>
+                                       <execution>
+                                               <phase>package</phase>
+                                               <goals>
+                                                       <goal>shade</goal>
+                                               </goals>
+                                               <configuration>
+                                                       <transformers>
+                                                               <transformer
+                                                                       implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                                                       <mainClass>org.opendaylight.protocol.bgp.testtool.Main</mainClass>
+                                                               </transformer>
+                                                       </transformers>
+                                                       <shadedArtifactAttached>true</shadedArtifactAttached>
+                                                       <shadedClassifierName>executable</shadedClassifierName>
+                                               </configuration>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+</project>
diff --git a/bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/Main.java b/bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/Main.java
new file mode 100644 (file)
index 0000000..fd7b8ec
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.testtool;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.rib.impl.BGPConnectionImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPDispatcherImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionProposalCheckerImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionProposalImpl;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposalChecker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * Starter class for testing.
+ */
+public class Main {
+
+       private final static Logger logger = LoggerFactory.getLogger(Main.class);
+
+       public static String usage = "DESCRIPTION:\n" + "\tCreates a server with given parameters. As long as it runs, it accepts connections "
+                       + "from PCCs.\n" + "USAGE:\n" + "\t-a, --address\n" + "\t\tthe ip address to which is this server bound.\n"
+                       + "\t\tFormat: x.x.x.x:y where y is port number.\n\n"
+                       + "\t\tThis IP address will appear in BGP Open message as BGP Identifier of the server.\n" +
+
+                       "\t-as\n" + "\t\t value of AS in the initial open message\n\n" +
+
+                       "\t-h, --holdtimer\n" + "\t\tin seconds, value of the desired holdtimer\n"
+                       + "\t\tAccording to RFC4271, recommended value for deadtimer is 90 seconds.\n"
+                       + "\t\tIf not set, this will be the default value.\n\n" +
+
+                       "\t--help\n" + "\t\tdisplay this help and exits\n\n" +
+
+                       "With no parameters, this help is printed.";
+
+       BGPDispatcherImpl dispatcher;
+
+       public Main() throws IOException {
+               this.dispatcher = new BGPDispatcherImpl(new DispatcherImpl(Executors.defaultThreadFactory()));
+       }
+
+       public static void main(final String[] args) throws NumberFormatException, IOException {
+               if (args.length == 0 || (args.length == 1 && args[0].equalsIgnoreCase("--help"))) {
+                       System.out.println(Main.usage);
+                       return;
+               }
+
+               InetSocketAddress address = null;
+               short holdTimerValue = 90;
+               ASNumber as = null;
+
+               int i = 0;
+               while (i < args.length) {
+                       if (args[i].equalsIgnoreCase("-a") || args[i].equalsIgnoreCase("--address")) {
+                               final String[] ip = args[i + 1].split(":");
+                               address = new InetSocketAddress(InetAddress.getByName(ip[0]), Integer.valueOf(ip[1]));
+                               i++;
+                       } else if (args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("--holdtimer")) {
+                               holdTimerValue = Short.valueOf(args[i + 1]);
+                               i++;
+                       } else if (args[i].equalsIgnoreCase("-as")) {
+                               as = new ASNumber(Long.valueOf(args[i + 1]));
+                               i++;
+                       } else {
+                               System.out.println("WARNING: Unrecognized argument: " + args[i]);
+                       }
+                       i++;
+               }
+
+               final Main m = new Main();
+
+               final BGPSessionListener sessionListener = new TestingListener((DispatcherImpl) m.dispatcher.getDispatcher());
+
+               final BGPSessionProposalImpl prop = new BGPSessionProposalImpl(holdTimerValue, as, new IPv4Address(InetAddress.getByName("25.25.25.2")));
+
+               final BGPSessionPreferences proposal = prop.getProposal();
+
+               prop.close();
+
+               final BGPSessionProposalChecker checker = new BGPSessionProposalCheckerImpl();
+
+               final BGPMessageParser parser = new BGPMessageFactory();
+
+               logger.debug(address + " " + sessionListener + " " + proposal + " " + checker);
+
+               final InetSocketAddress addr = address;
+               m.dispatcher.createClient(new BGPConnectionImpl(addr, sessionListener, proposal, checker), parser);
+       }
+}
diff --git a/bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/TestingListener.java b/bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/TestingListener.java
new file mode 100644 (file)
index 0000000..47da82b
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.testtool;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+
+/**
+ * Testing BGP Listener.
+ */
+public class TestingListener extends BGPSessionListener {
+       private static final Logger logger = LoggerFactory.getLogger(TestingListener.class);
+
+       DispatcherImpl d;
+
+       TestingListener(final DispatcherImpl d) {
+               this.d = d;
+       }
+
+       @Override
+       public void onMessage(final BGPMessage message) {
+               logger.info("Client Listener: message received: {}", message.toString());
+       }
+
+       @Override
+       public void onSessionUp(final Set<BGPTableType> remoteParams) {
+               logger.info("Client Listener: Session Up.");
+       }
+
+       @Override
+       public void onSessionDown(final BGPSession session, final Exception e) {
+               logger.info("Client Listener: Connection lost.");
+               session.close();
+               this.d.stop();
+       }
+
+       @Override
+       public void onSessionTerminated(final BGPError cause) {
+               logger.info("Client Listener: Connection lost: {}.", cause);
+               this.d.stop();
+       }
+}
diff --git a/bgp/testtool/src/main/resources/logback.xml b/bgp/testtool/src/main/resources/logback.xml
new file mode 100644 (file)
index 0000000..5541272
--- /dev/null
@@ -0,0 +1,16 @@
+<configuration>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+               <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+                       <level>TRACE</level>
+               </filter>
+               <encoder>
+                       <pattern>[%d{HH:mm:ss.SSS}] [%thread] %-5level %logger{10} - %msg%n</pattern>
+               </encoder>
+       </appender>
+
+    <logger name="org.opendaylight.protocol" level="TRACE" />
+
+    <root level="TRACE">
+        <appender-ref ref="STDOUT" />
+    </root>
+</configuration>
diff --git a/bgp/testtool/src/test/java/org/opendaylight/protocol/bgp/testtool/BGPSpeakerMock.java b/bgp/testtool/src/test/java/org/opendaylight/protocol/bgp/testtool/BGPSpeakerMock.java
new file mode 100644 (file)
index 0000000..b6c11a1
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.testtool;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.rib.impl.BGPConnectionImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPInputStream;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionFactory;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionProposalCheckerImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionProposalImpl;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnectionFactory;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4;
+
+public class BGPSpeakerMock {
+
+       DispatcherImpl dispatcher;
+
+       BGPSpeakerMock() throws IOException {
+               this.dispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+       }
+
+       public static void main(final String[] args) throws IOException {
+
+               final BGPSpeakerMock m = new BGPSpeakerMock();
+
+               final BGPMessageParser parser = new BGPMessageFactory();
+
+               m.dispatcher.createServer(new InetSocketAddress("127.0.0.2", 12345), new BGPConnectionFactory() {
+                       @Override
+                       public BGPConnection createProtocolConnection(final InetSocketAddress address) {
+                               final BGPSessionProposalImpl prop = new BGPSessionProposalImpl((short) 90, new ASNumber(25), IPv4.FAMILY.addressForString("127.0.0.2"));
+                               final BGPSessionPreferences prefs = prop.getProposal();
+                               try {
+                                       prop.close();
+                               } catch (final IOException e) {
+                                       e.printStackTrace();
+                               }
+                               return new BGPConnectionImpl(address, new SpeakerSessionListener(m.dispatcher), prefs, new BGPSessionProposalCheckerImpl());
+                       }
+               }, new BGPSessionFactory(parser), BGPInputStream.FACTORY);
+       }
+}
diff --git a/bgp/testtool/src/test/java/org/opendaylight/protocol/bgp/testtool/SpeakerSessionListener.java b/bgp/testtool/src/test/java/org/opendaylight/protocol/bgp/testtool/SpeakerSessionListener.java
new file mode 100644 (file)
index 0000000..391b299
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.testtool;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+
+public class SpeakerSessionListener extends BGPSessionListener {
+       private static final Logger logger = LoggerFactory.getLogger(SpeakerSessionListener.class);
+
+       DispatcherImpl d;
+
+       SpeakerSessionListener(final DispatcherImpl d) {
+               this.d = d;
+       }
+
+       @Override
+       public void onSessionUp(final Set<BGPTableType> remote) {
+               logger.info("Server: Session is up.");
+       }
+
+       @Override
+       public void onSessionTerminated(final BGPError cause) {
+               logger.info("Server: Session terminated: {}", cause);
+       }
+
+       @Override
+       public void onSessionDown(final BGPSession session, final Exception e) {
+               logger.info("Server: Session down.");
+               session.close();
+               this.d.stop();
+       }
+
+       @Override
+       public void onMessage(final BGPMessage message) {
+               logger.info("Server: Message received: {}", message);
+               this.d.stop();
+       }
+}
diff --git a/bgp/util/.gitignore b/bgp/util/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/bgp/util/.project b/bgp/util/.project
new file mode 100644 (file)
index 0000000..8e3aa67
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>util</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bgp/util/pom.xml b/bgp/util/pom.xml
new file mode 100644 (file)
index 0000000..22b7224
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>bgp-parent</artifactId>
+               <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>bgp-util</artifactId>
+       <description>BGP utilities</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-parser-api</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-linkstate</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>bgp-concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.guava</groupId>
+                       <artifactId>guava</artifactId>
+                       <version>${guava.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.code.findbugs</groupId>
+                       <artifactId>jsr305</artifactId>
+                       <version>2.0.1</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-api</artifactId>
+                       <version>${slf4j.version}</version>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.bgp.util,
+                                               </Export-Package>
+                                               <Import-Package>
+                                                       org.opendaylight.protocol.bgp.concepts,
+                            org.opendaylight.protocol.bgp.linkstate,
+                                                       org.opendaylight.protocol.bgp.parser,
+                                                       org.opendaylight.protocol.concepts,
+                            org.opendaylight.protocol.util,
+                                                       com.google.common.*, 
+                                                       org.opendaylight.protocol.concepts, 
+                                                       org.apache.commons.*,
+                                                       org.slf4j
+                                               </Import-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>BGP-UTIL Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/AbstractBGPObject.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/AbstractBGPObject.java
new file mode 100644 (file)
index 0000000..6fab8b7
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Implementation of BGPObject that wraps up BGPNode and BGPLink.
+ */
+public abstract class AbstractBGPObject implements BGPObject {
+       private static final long serialVersionUID = 1L;
+       private final BaseBGPObjectState state;
+
+       protected AbstractBGPObject(final BaseBGPObjectState state) {
+               this.state = state;
+       }
+
+       @Override
+       public BaseBGPObjectState currentState() {
+               return state;
+       }
+
+       @Override
+       public synchronized final String toString(){
+               return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("state", this.state);
+               return toStringHelper;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((state == null) ? 0 : state.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               AbstractBGPObject other = (AbstractBGPObject) obj;
+               if (state == null) {
+                       if (other.state != null)
+                               return false;
+               } else if (!state.equals(other.state))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/AbstractBGPPrefix.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/AbstractBGPPrefix.java
new file mode 100644 (file)
index 0000000..c060410
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.parser.BGPPrefix;
+import org.opendaylight.protocol.bgp.parser.BGPPrefixState;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import com.google.common.base.Preconditions;
+
+/**
+ * Super class for BGPIpvXPrefixImpl.
+ * 
+ * @param <T> extends NetworkAddress<T>
+ */
+public abstract class AbstractBGPPrefix<T extends NetworkAddress<T>> extends AbstractBGPObject implements BGPPrefix<T> {
+       private static final long serialVersionUID = 1L;
+       private final PrefixIdentifier<T> descriptor;
+
+       protected AbstractBGPPrefix(final BaseBGPObjectState base, final PrefixIdentifier<T> descriptor, final NetworkPrefixState prefixState) {
+               super(new BGPPrefixState(base, prefixState));
+               Preconditions.checkNotNull(descriptor);
+               this.descriptor = descriptor;
+       }
+
+       @Override
+       public final PrefixIdentifier<T> getPrefixIdentifier() {
+               return this.descriptor;
+       }
+
+       @Override
+       final public BGPPrefixState currentState() {
+               return (BGPPrefixState) super.currentState();
+       }
+}
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/AbstractBGPRoute.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/AbstractBGPRoute.java
new file mode 100644 (file)
index 0000000..a7c3a31
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.parser.BGPRoute;
+import org.opendaylight.protocol.bgp.parser.BGPRouteState;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Super class for BGPIpvXPrefixImpl.
+ * 
+ * @param <T> extends NetworkAddress<T>
+ */
+public abstract class AbstractBGPRoute<T extends NetworkAddress<T>> extends AbstractBGPObject implements BGPRoute<T> {
+       private static final long serialVersionUID = 1L;
+       private final Prefix<T> name;
+
+       protected AbstractBGPRoute(final Prefix<T> name, final BaseBGPObjectState base, final NetworkRouteState<T> routeState) {
+               super(new BGPRouteState<T>(base, routeState));
+               this.name = Preconditions.checkNotNull(name);
+       }
+
+       @Override
+       final public BGPRouteState<T> currentState() {
+               return (BGPRouteState<T>) super.currentState();
+       }
+
+       @Override
+       final public Prefix<T> getName() {
+               return this.name;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               final AbstractBGPRoute<?> other = (AbstractBGPRoute<?>) obj;
+               if (this.name == null) {
+                       if (other.name != null)
+                               return false;
+               } else if (!this.name.equals(other.name))
+                       return false;
+               return true;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("name", this.name);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv4PrefixImpl.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv4PrefixImpl.java
new file mode 100644 (file)
index 0000000..ba7beac
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
+
+/**
+ * Implementation of {@link AbstractBGPPrefix}.
+ */
+public final class BGPIPv4PrefixImpl extends AbstractBGPPrefix<IPv4Address> {
+       private static final long serialVersionUID = 1L;
+
+       public BGPIPv4PrefixImpl(final BaseBGPObjectState base, final IPv4PrefixIdentifier identifier, final NetworkPrefixState prefixState) {
+               super(base, identifier, prefixState);
+       }
+}
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv4RouteImpl.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv4RouteImpl.java
new file mode 100644 (file)
index 0000000..cce08af
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+
+/**
+ * Implementation of {@link AbstractBGPPrefix}.
+ */
+public final class BGPIPv4RouteImpl extends AbstractBGPRoute<IPv4Address> {
+       private static final long serialVersionUID = 1L;
+
+       public BGPIPv4RouteImpl(final Prefix<IPv4Address> prefix, final BaseBGPObjectState base,
+                       final NetworkRouteState<IPv4Address> prefixState) {
+               super(prefix, base, prefixState);
+       }
+}
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv6PrefixImpl.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv6PrefixImpl.java
new file mode 100644 (file)
index 0000000..3c505fc
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+
+/**
+ * Implementation of {@link AbstractBGPPrefix}
+ */
+public class BGPIPv6PrefixImpl extends AbstractBGPPrefix<IPv6Address> {
+       private static final long serialVersionUID = 1L;
+
+       public BGPIPv6PrefixImpl(final BaseBGPObjectState base, final PrefixIdentifier<IPv6Address> descriptor,
+                       final NetworkPrefixState prefixState) {
+               super(base, descriptor, prefixState);
+       }
+}
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv6RouteImpl.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPIPv6RouteImpl.java
new file mode 100644 (file)
index 0000000..0b672ce
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+
+/**
+ * Implementation of {@link AbstractBGPPrefix}.
+ */
+public final class BGPIPv6RouteImpl extends AbstractBGPRoute<IPv6Address> {
+       private static final long serialVersionUID = 1L;
+
+       public BGPIPv6RouteImpl(final Prefix<IPv6Address> prefix, final BaseBGPObjectState base, final NetworkRouteState<IPv6Address> prefixState) {
+               super(prefix, base, prefixState);
+       }
+}
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPLinkImpl.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPLinkImpl.java
new file mode 100644 (file)
index 0000000..ec55c8c
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.parser.BGPLink;
+import org.opendaylight.protocol.bgp.parser.BGPLinkState;
+
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * 
+ * BGP Link-State Link object is a composition object of BGPObject (so it can be contained in addedObjects in Update
+ * Message) and Network Link, that merges the attributes from Link-State NLRI about Links.
+ * 
+ */
+public final class BGPLinkImpl extends AbstractBGPObject implements BGPLink {
+
+       private static final long serialVersionUID = -226135392855622720L;
+
+       private final LinkIdentifier linkIdentifier;
+
+       /**
+        * Creates a new Link with given arguments.
+        * 
+        * @param origin BGPOrigin
+        * @param aggregator BGPAggregator
+        * @param linkIdentifier LinkIdentifier
+        * @param linkAttributes NetworkLink
+        */
+       public BGPLinkImpl(final BaseBGPObjectState base, final LinkIdentifier linkIdentifier, final NetworkLinkState linkState) {
+               super(new BGPLinkState(base, linkState));
+               Preconditions.checkNotNull(linkIdentifier);
+               this.linkIdentifier = linkIdentifier;
+       }
+
+       @Override
+       public LinkIdentifier getLinkIdentifier() {
+               return this.linkIdentifier;
+       }
+
+       @Override
+       public BGPLinkState currentState() {
+               return (BGPLinkState) super.currentState();
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.linkIdentifier == null) ? 0 : this.linkIdentifier.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (!(obj instanceof BGPLinkImpl))
+                       return false;
+               final BGPLinkImpl other = (BGPLinkImpl) obj;
+               if (this.linkIdentifier == null) {
+                       if (other.linkIdentifier != null)
+                               return false;
+               } else if (!this.linkIdentifier.equals(other.linkIdentifier))
+                       return false;
+               return true;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("linkIdentifier", this.linkIdentifier);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPNodeImpl.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BGPNodeImpl.java
new file mode 100644 (file)
index 0000000..3e9ee8a
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import org.opendaylight.protocol.bgp.concepts.BGPAggregator;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.parser.BGPNode;
+import org.opendaylight.protocol.bgp.parser.BGPNodeState;
+
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNode;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * 
+ * BGP Link-State Node object is a composition object of BGPObject (so it can be contained in addedObjects in Update
+ * Message) and Network Node, that merges the attributes from Link-State NLRI about Nodes.
+ * 
+ */
+public final class BGPNodeImpl extends AbstractBGPObject implements BGPNode {
+       private static final long serialVersionUID = 1L;
+
+       private final NodeIdentifier nodeIdentifier;
+
+       /**
+        * Creates this object with given arguments.
+        * 
+        * @param origin {@link BGPOrigin}
+        * @param aggregator {@link BGPAggregator}
+        * @param nodeIdentifier {@link NodeIdentifier}
+        * @param nodeAttributes {@link NetworkNode}
+        */
+       public BGPNodeImpl(final BaseBGPObjectState base, final NodeIdentifier nodeIdentifier, final NetworkNodeState nodeState) {
+               super(new BGPNodeState(base, nodeState));
+               this.nodeIdentifier = nodeIdentifier;
+       }
+
+       @Override
+       public BGPNodeState currentState() {
+               return (BGPNodeState) super.currentState();
+       }
+
+       @Override
+       public NodeIdentifier getNodeIdentifier() {
+               return this.nodeIdentifier;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               toStringHelper.add("nodeDescriptor", this.nodeIdentifier);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.nodeIdentifier == null) ? 0 : this.nodeIdentifier.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final BGPNodeImpl other = (BGPNodeImpl) obj;
+               if (this.nodeIdentifier == null) {
+                       if (other.nodeIdentifier != null)
+                               return false;
+               } else if (!this.nodeIdentifier.equals(other.nodeIdentifier))
+                       return false;
+               return true;
+       }
+}
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BinaryBGPDumpFileParser.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/BinaryBGPDumpFileParser.java
new file mode 100644 (file)
index 0000000..9e31fcb
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * This extracter extracts BGP messages in binary form from a file in MRT format.
+ * (http://www.ripe.net/data-tools/stats/ris/ris-raw-data) The parser detects BGP messages by searching for 16 FF bytes,
+ * everything else before or after is ignored.
+ */
+@Immutable
+public final class BinaryBGPDumpFileParser {
+
+       private static final byte ff = (byte) 255;
+       private static final Logger LOG = LoggerFactory.getLogger(BinaryBGPDumpFileParser.class);
+       private static final int MINIMAL_LENGTH = 19;
+
+       /**
+        * Extract BGP messages from binary file in MRT format.
+        * 
+        * @param file file with BGP messages in binary form.
+        * @return list with byte arrays representing extracted messages.
+        * @throws IOException
+        */
+       public static List<byte[]> parseMessages(final byte[] byteArray) {
+
+               final List<byte[]> messages = Lists.newLinkedList();
+               // search for 16 FFs
+               for (int i = 0; i < byteArray.length; i++) {
+                       final byte b = byteArray[i];
+
+                       // Marker start
+                       if (b == ff) {
+                               final int start = i;
+                               int ffCount = 0;
+                               for (int j = i; j < i + (17); j++) {
+                                       // Check marker
+                                       if (byteArray[j] == ff) {
+                                               ffCount++;
+                                       } else if (ffCount == 16) {
+                                               if (j == (i + 16)) {
+                                                       // Parse length
+                                                       final int length = UnsignedBytes.toInt(byteArray[j]) * 256 + UnsignedBytes.toInt(byteArray[j + 1]);
+
+                                                       Preconditions.checkArgument(length >= MINIMAL_LENGTH, "Invalid message at index " + start
+                                                                       + ", length atribute is lower than " + MINIMAL_LENGTH);
+
+                                                       final byte[] message = Arrays.copyOfRange(byteArray, start, start + length);
+                                                       messages.add(message);
+                                                       j += length - 16;
+                                               }
+                                               i = j;
+                                               break;
+                                       } else {
+                                               break;
+                                       }
+                               }
+                       }
+
+               }
+               LOG.info("Succesfully extracted " + messages.size() + " messages");
+               return messages;
+       }
+}
diff --git a/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/HexDumpBGPFileParser.java b/bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/HexDumpBGPFileParser.java
new file mode 100644 (file)
index 0000000..7770bc2
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.concurrent.Immutable;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.List;
+
+/**
+ * Read text file, parse BGP messages. File can contain comments or other data. BGP messages are detected using 16 ff marker.
+ * New lines and spaces are ignored. Use {@link ByteArray#bytesToHexString(byte[])} for serializing bytes to this format.
+ */
+@Immutable
+public class HexDumpBGPFileParser {
+       private static final int MINIMAL_LENGTH = 19;
+       private static final Logger LOG = LoggerFactory.getLogger(HexDumpBGPFileParser.class);
+       private static final String ff_16 = Strings.repeat("FF", 16);
+
+       public static List<byte[]> parseMessages(File file) {
+               Preconditions.checkArgument(file != null, "Filename cannot be null");
+               Preconditions.checkArgument(file.exists() && file.canRead(), "File " + file + " does not exist or is not readable");
+               String content;
+               try {
+                       content = Files.toString(file, Charset.defaultCharset());
+               } catch (IOException e) {
+                       throw new RuntimeException(e);
+               }
+               return parseMessages(content);
+       }
+
+       public static List<byte[]> parseMessages(String content) {
+               content = clearWhiteSpace_toUpper(content);
+               // search for 16 FFs
+
+               List<byte[]> messages = Lists.newLinkedList();
+               int idx = 0;
+               while ((idx = content.indexOf(ff_16, idx)) > -1) {
+                       // next 2 bytes are length
+                       int lengthIdx = idx + 16 * 2;
+                       int messageIdx = lengthIdx + 4;
+                       String hexLength = content.substring(lengthIdx, messageIdx);
+                       byte[] byteLength = null;
+                       try {
+                               byteLength = Hex.decodeHex(hexLength.toCharArray());
+                       } catch (DecoderException e) {
+                               throw new RuntimeException(e);
+                       }
+                       int length = ByteArray.bytesToInt(byteLength);
+                       int messageEndIdx = idx + length * 2;
+
+                       // Assert that message is longer than minimum 19(header.length == 19)
+                       // If length in BGP message would be 0, loop would never end
+                       Preconditions.checkArgument(length >=  MINIMAL_LENGTH,
+                                       "Invalid message at index " + idx
+                                                       + ", length atribute is lower than " + MINIMAL_LENGTH);
+
+                       String hexMessage = content.substring(idx, messageEndIdx);
+                       byte[] message = null;
+                       try {
+                               message = Hex.decodeHex(hexMessage.toCharArray());
+                       } catch (DecoderException e) {
+                               new RuntimeException(e);
+                       }
+                       messages.add(message);
+                       idx = messageEndIdx;
+               }
+               LOG.info("Succesfully extracted " + messages.size() + " messages");
+               return messages;
+       }
+
+       @VisibleForTesting
+       static String clearWhiteSpace_toUpper(String line){
+               return line.replaceAll("\\s", "").toUpperCase();
+       }
+
+}
diff --git a/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/BGPBinaryFileParserTest.java b/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/BGPBinaryFileParserTest.java
new file mode 100644 (file)
index 0000000..7c8b871
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.junit.Test;
+
+public class BGPBinaryFileParserTest {
+
+       private final byte ff = (byte) 255;
+
+       @Test
+       public void testCorrectExtraction() throws IOException {
+               final List<byte[]> parsedMessages = extractFromFile("/BgpMessages");
+
+               assertThat(parsedMessages.size(), is(43));
+
+               // 1st message
+               assertThat(parsedMessages.get(0).length, is(19));
+               checkMarker(parsedMessages);
+               assertThat(parsedMessages.get(0)[16], is((byte) 0));
+               assertThat(parsedMessages.get(0)[17], is((byte) 19));
+               assertThat(parsedMessages.get(0)[18], is((byte) 4));
+
+               // 39th message
+               assertThat(parsedMessages.get(38).length, is(91));
+               checkMarker(parsedMessages);
+               assertThat(parsedMessages.get(38)[16], is((byte) 0));
+               assertThat(parsedMessages.get(38)[17], is((byte) 91));
+               assertThat(parsedMessages.get(38)[18], is((byte) 2));
+               assertThat(parsedMessages.get(38)[90], is((byte) 236));
+
+       }
+
+       private List<byte[]> extractFromFile(final String fileName) throws IOException {
+               final InputStream is = BGPBinaryFileParserTest.class.getResourceAsStream(fileName);
+               assertNotNull("File not found - " + fileName);
+               if (is == null)
+                       throw new IOException("Failed to get resource " + fileName);
+
+               final ByteArrayOutputStream bis = new ByteArrayOutputStream();
+               final byte[] data = new byte[1000];
+               int nRead = 0;
+               while ((nRead = is.read(data, 0, data.length)) != -1) {
+                       bis.write(data, 0, nRead);
+               }
+               bis.flush();
+               return BinaryBGPDumpFileParser.parseMessages(bis.toByteArray());
+       }
+
+       private void checkMarker(final List<byte[]> parsedMessages) {
+               for (int i = 0; i < 16; i++) {
+                       assertThat(parsedMessages.get(0)[i], is(this.ff));
+               }
+       }
+
+       /**
+        * In BgpMessages_wrong_header file, first FF sequence is corrupted
+        * 
+        * @throws IOException
+        */
+       @Test
+       public void testCorruptedHeader() throws IOException {
+               final List<byte[]> parsedMessages = extractFromFile("/BgpMessages_wrong_header");
+               assertEquals(42, parsedMessages.size());
+       }
+
+}
diff --git a/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/BGPHexFileParserTest.java b/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/BGPHexFileParserTest.java
new file mode 100644 (file)
index 0000000..39d958e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import java.io.File;
+import java.util.List;
+
+import org.junit.Test;
+
+public class BGPHexFileParserTest {
+
+       public static final String hexDumpFileName = "/bgp_hex.txt";
+       private final String fileNameInvalid = "BgpMessage_Hex_InvalidLength";
+       private final int expectedSize = 9;
+
+       @Test
+       public void testCleanWhiteSpace() {
+               final String input = "abc def\r\nghi\nj";
+               assertEquals("ABCDEFGHIJ", HexDumpBGPFileParser.clearWhiteSpace_toUpper(input));
+       }
+
+       @Test
+       public void testParsing() {
+               final List<byte[]> result = HexDumpBGPFileParser.parseMessages(new File(getClass().getResource(BGPHexFileParserTest.hexDumpFileName).getFile()));
+               assertEquals(this.expectedSize, result.size());
+       }
+
+       @Test
+       public void testParsingInvalidMessage() {
+               try {
+                       HexDumpBGPFileParser.parseMessages(new File(this.fileNameInvalid));
+                       fail("Exception should have occured.");
+               } catch (final IllegalArgumentException e) {
+                       assertThat(e.getMessage(), containsString("File BgpMessage_Hex_InvalidLength does not exist or is not readable"));
+               }
+       }
+}
diff --git a/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/LinkTest.java b/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/LinkTest.java
new file mode 100644 (file)
index 0000000..37880ce
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collections;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.util.BGPLinkImpl;
+import org.opendaylight.protocol.util.DefaultingTypesafeContainer;
+
+public class LinkTest {
+
+       @Test
+       public void testLinkImpl() {
+
+               final BaseBGPObjectState state1 = new BaseBGPObjectState(BGPOrigin.EGP, null);
+               final NetworkObjectState empty = new NetworkObjectState(null, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+               final NetworkLinkState nstate1 = new NetworkLinkState(empty, new DefaultingTypesafeContainer<Metric<?>>(), null, LinkProtectionType.UNPROTECTED, null, null, null);
+
+               final BGPLinkImpl link1 = new BGPLinkImpl(state1, new LinkIdentifier(new TopologyIdentifier(512), null, null), nstate1);
+               final BGPLinkImpl link2 = new BGPLinkImpl(state1, new LinkIdentifier(new TopologyIdentifier(512), null, null), nstate1);
+
+               assertEquals(link1, link2);
+               assertEquals(link1.toString(), link2.toString());
+               assertEquals(link1.hashCode(), link2.hashCode());
+               assertEquals(link1.getLinkIdentifier(), link2.getLinkIdentifier());
+               assertEquals(link1.currentState(), link2.currentState());
+       }
+}
diff --git a/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/NodeTest.java b/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/NodeTest.java
new file mode 100644 (file)
index 0000000..1c32f6d
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.util.BGPNodeImpl;
+
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+
+public class NodeTest {
+
+       @Test
+       public void testNodeImpl() {
+               final BGPNodeImpl node1 = new BGPNodeImpl(new BaseBGPObjectState(BGPOrigin.INCOMPLETE, null), null, NetworkNodeState.EMPTY);
+               final BGPNodeImpl node2 = new BGPNodeImpl(new BaseBGPObjectState(BGPOrigin.EGP, null), null, NetworkNodeState.EMPTY);
+
+               assertFalse(node1.equals(node2));
+               assertNotSame(node1.hashCode(), node2.hashCode());
+               assertEquals(node1.toString(), node1.toString());
+               assertNull(node1.currentState().getAggregator());
+               assertEquals(node1.currentState().getOrigin(), BGPOrigin.INCOMPLETE);
+               assertEquals(node1.getNodeIdentifier(), node2.getNodeIdentifier());
+               assertEquals(node2, new BGPNodeImpl(new BaseBGPObjectState(BGPOrigin.EGP, null), null, NetworkNodeState.EMPTY));
+       }
+}
diff --git a/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/PrefixTest.java b/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/PrefixTest.java
new file mode 100644 (file)
index 0000000..c020d39
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+
+import java.util.Collections;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.util.BGPIPv4PrefixImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6PrefixImpl;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFRouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.RouteTag;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv6PrefixIdentifier;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+public class PrefixTest {
+       final BaseBGPObjectState base = new BaseBGPObjectState(BGPOrigin.EGP, null);
+       final NetworkObjectState state = new NetworkObjectState(new ASPath(Lists.newArrayList(new ASNumber(10L))), Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+       final NetworkPrefixState prefixState = new NetworkPrefixState(this.state, Sets.<RouteTag> newTreeSet(), null);
+
+       final BGPIPv4PrefixImpl r4 = new BGPIPv4PrefixImpl(this.base, new IPv4PrefixIdentifier(new NodeIdentifier(null, null, null, new OSPFRouterIdentifier(new byte[] {
+                       1, 2, 3, 4 })), IPv4.FAMILY.prefixForString("172.168.4.5/16")), this.prefixState);
+       final BGPIPv6PrefixImpl r6 = new BGPIPv6PrefixImpl(this.base, new IPv6PrefixIdentifier(new NodeIdentifier(null, null, null, new OSPFRouterIdentifier(new byte[] {
+                       1, 2, 3, 4 })), IPv6.FAMILY.prefixForString("2001::4/32")), this.prefixState);
+
+       @Test
+       public void testIPv4Prefix() {
+               final BGPIPv4PrefixImpl r2 = new BGPIPv4PrefixImpl(this.base, new IPv4PrefixIdentifier(new NodeIdentifier(null, null, null, new OSPFRouterIdentifier(new byte[] {
+                               1, 2, 3, 4 })), IPv4.FAMILY.prefixForString("172.168.4.5/16")), this.prefixState);
+
+               assertEquals(this.r4, r2);
+               assertEquals(this.r4.hashCode(), r2.hashCode());
+               assertNotSame(this.r4, this.r6);
+       }
+
+       @Test
+       public void testIPv6Route() {
+               final BGPIPv6PrefixImpl r2 = new BGPIPv6PrefixImpl(this.base, new IPv6PrefixIdentifier(new NodeIdentifier(null, null, null, new OSPFRouterIdentifier(new byte[] {
+                               1, 2, 3, 4 })), IPv6.FAMILY.prefixForString("2001::4/32")), this.prefixState);
+
+               assertEquals(this.r6.currentState(), r2.currentState());
+               assertEquals(this.r6.toString(), r2.toString());
+               assertEquals(this.r6.getPrefixIdentifier(), r2.getPrefixIdentifier());
+       }
+}
diff --git a/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/RouteTest.java b/bgp/util/src/test/java/org/opendaylight/protocol/bgp/util/RouteTest.java
new file mode 100644 (file)
index 0000000..d54127b
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+
+public class RouteTest {
+
+       BaseBGPObjectState base = new BaseBGPObjectState(BGPOrigin.EGP, null);
+       final NetworkRouteState<IPv4Address> prefix4State = new NetworkRouteState<>(IPv4NextHop.forString("128.54.8.9"));
+       final NetworkRouteState<IPv6Address> prefix6State = new NetworkRouteState<>(IPv6NextHop.forString("2001::4"));
+       final BGPIPv4RouteImpl r4 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("172.168.4.6/24"), this.base, this.prefix4State);
+       final BGPIPv6RouteImpl r6 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("2001::4/32"), this.base, this.prefix6State);
+
+       @Test
+       public void testIPv4Route() {
+               final BGPIPv4RouteImpl r2 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("172.168.4.6/24"), this.base, this.prefix4State);
+
+               assertEquals(this.r4, r2);
+               assertEquals(this.r4.hashCode(), r2.hashCode());
+               assertNotSame(this.r4, this.r6);
+       }
+
+       @Test
+       public void testIPv6Route() {
+               final BGPIPv6RouteImpl r2 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("2001::4/32"), this.base, this.prefix6State);
+
+               assertEquals(this.r6.currentState(), r2.currentState());
+               assertEquals(this.r6.toString(), r2.toString());
+               assertEquals(this.r6.getName(), r2.getName());
+       }
+}
diff --git a/bgp/util/src/test/resources/BgpMessage_Hex_InvalidLength b/bgp/util/src/test/resources/BgpMessage_Hex_InvalidLength
new file mode 100644 (file)
index 0000000..6f6569d
--- /dev/null
@@ -0,0 +1,2 @@
+ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff\r
+00 00 02\r
diff --git a/bgp/util/src/test/resources/BgpMessages b/bgp/util/src/test/resources/BgpMessages
new file mode 100644 (file)
index 0000000..c923b86
Binary files /dev/null and b/bgp/util/src/test/resources/BgpMessages differ
diff --git a/bgp/util/src/test/resources/BgpMessages_wrong_header b/bgp/util/src/test/resources/BgpMessages_wrong_header
new file mode 100644 (file)
index 0000000..1bb5dd8
Binary files /dev/null and b/bgp/util/src/test/resources/BgpMessages_wrong_header differ
diff --git a/bgp/util/src/test/resources/OpenMessage b/bgp/util/src/test/resources/OpenMessage
new file mode 100644 (file)
index 0000000..9975c32
Binary files /dev/null and b/bgp/util/src/test/resources/OpenMessage differ
diff --git a/bgp/util/src/test/resources/bgp_hex.txt b/bgp/util/src/test/resources/bgp_hex.txt
new file mode 100644 (file)
index 0000000..f0920be
--- /dev/null
@@ -0,0 +1,86 @@
+Receive BGP Update message for 0x804b6a0: Length = 61
+   
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 3d 01 04 00 14 00 b4    14 14 14 14 20 02 06 01    
+04 00 01 00 01 02 06 01    04 00 1b 00 01 02 02 80    
+00 02 02 02 00 02 06 41    04 00 00 00 14 
+
+Receive BGP Update message for 0x804b6a0: Length = 151
+   
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 40 02 00 00 00 1f 40    01 01 00 40 02 0a 02 02    
+00 00 00 64 00 00 00 46    40 03 04 0a 01 01 0a 40    
+05 04 00 00 00 64 20 46    01 02 02 20 46 01 01 01    
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 40 02 00 00 00 1f 40    01 01 00 40 02 0a 02 02    
+00 00 00 64 00 00 00 5a    40 03 04 0a 01 01 0a 40    
+05 04 00 00 00 64 20 5a    01 02 02 20 5a 01 01 01    
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 17 02 00 00 00 00 
+
+Receive BGP Update message for 0x804b6a0: Length = 1021
+   
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 70 02 00 00 00 59 90    0e 00 37 00 1b 01 04 0a    
+01 01 0a 00 00 01 00 2a    01 00 00 00 01 00 00 13    
+01 02 00 04 64 00 00 00    01 06 00 07 00 00 00 00    
+00 01 00 01 01 00 0b 01    06 00 07 00 00 00 00 00    
+02 03 40 01 01 00 40 02    06 02 01 00 00 00 64 40    
+05 04 00 00 00 64 80 ff    07 01 13 00 03 15 00 00    
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+01 28 02 00 00 01 11 90    0e 00 ef 00 1b 01 04 0a    
+01 01 0a 00 00 01 00 2a    01 00 00 00 01 00 00 13    
+01 02 00 04 64 00 00 00    01 06 00 07 00 00 00 00    
+00 10 00 01 01 00 0b 01    06 00 07 00 00 00 00 00    
+10 03 00 01 00 2a 01 00    00 00 01 00 00 13 01 02    
+00 04 64 00 00 00 01 06    00 07 00 00 00 00 00 10    
+00 01 01 00 0b 01 06 00    07 00 00 00 00 00 10 01    
+00 01 00 2a 01 00 00 00    01 00 00 13 01 02 00 04    
+64 00 00 00 01 06 00 07    00 00 00 00 00 02 00 01    
+01 00 0b 01 06 00 07 00    00 00 00 00 10 01 00 01    
+00 2a 01 00 00 00 01 00    00 13 01 02 00 04 64 00    
+00 00 01 06 00 07 00 00    00 00 00 02 00 01 01 00    
+0b 01 06 00 07 00 00 00    00 00 02 03 00 01 00 2a    
+01 00 00 00 01 00 00 13    01 02 00 04 64 00 00 00    
+01 06 00 07 00 00 00 00    00 01 00 01 01 00 0b 01    
+06 00 07 00 00 00 00 00    10 03 40 01 01 00 40 02    
+06 02 01 00 00 00 64 40    05 04 00 00 00 64 80 ff    
+07 01 13 00 03 0a 00 00    ff ff ff ff ff ff ff ff    
+ff ff ff ff ff ff ff ff    01 56 02 00 00 01 3f 90    
+0e 01 1d 00 1b 01 04 0a    01 01 0a 00 00 01 00 2a    
+01 00 00 00 01 00 00 13    01 02 00 04 64 00 00 00    
+01 06 00 07 00 00 00 00    00 10 03 01 01 00 0b 01    
+06 00 07 00 00 00 00 00    10 00 00 01 00 2a 01 00    
+00 00 01 00 00 13 01 02    00 04 64 00 00 00 01 06    
+00 07 00 00 00 00 00 10    03 01 01 00 0b 01 06 00    
+07 00 00 00 00 00 01 00    00 01 00 2a 01 00 00 00    
+01 00 00 13 01 02 00 04    64 00 00 00 01 06 00 07    
+00 00 00 00 00 10 01 01    01 00 0b 01 06 00 07 00    
+00 00 00 00 10 00 00 01    00 2a 01 00 00 00 01 00    
+00 13 01 02 00 04 64 00    00 00 01 06 00 07 00 00    
+00 00 00 10 01 01 01 00    0b 01 06 00 07 00 00 00    
+00 00 02 00 00 01 00 2a    01 00 00 00 01 00 00 13    
+01 02 00 04 64 00 00 00    01 06 00 07 00 00 00 00    
+00 02 03 01 01 00 0b 01    06 00 07 00 00 00 00 00    
+02 00 00 01 00 2a 01 00    00 00 01 00 00 13 01 02    
+00 04 64 00 00 00 01 06    00 07 00 00 00 00 00 02    
+03 01 01 00 0b 01 06 00    07 00 00 00 00 00 01 00    
+40 01 01 00 40 02 06 02    01 00 00 00 64 40 05 04    
+00 00 00 64 80 ff 07 01    13 00 03 00 00 00 ff ff    
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff 00 f2    
+02 00 00 00 db 90 0e 00    c3 00 1b 01 04 0a 01 01    
+0a 00 00 02 00 1b 01 00    00 00 01 00 00 13 01 02    
+00 04 64 00 00 00 01 06    00 07 00 00 00 00 00 10    
+03 00 02 00 1b 01 00 00    00 01 00 00 13 01 02 00    
+04 64 00 00 00 01 06 00    07 00 00 00 00 00 10 01    
+00 02 00 1b 01 00 00 00    01 00 00 13 01 02 00 04    
+64 00 00 00 01 06 00 07    00 00 00 00 00 10 00 00    
+02 00 1b 01 00 00 00 01    00 00 13 01 02 00 04 64    
+00 00 00 01 06 00 07 00    00 00 00 00 02 03 00 02    
+00 1b 01 00 00 00 01 00    00 13 01 02 00 04 64 00    
+00 00 01 06 00 07 00 00    00 00 00 02 00 00 02 00    
+1b 01 00 00 00 01 00 00    13 01 02 00 04 64 00 00    
+00 01 06 00 07 00 00 00    00 00 01 00 40 01 01 00    
+40 02 06 02 01 00 00 00    64 40 05 04 00 00 00 64    
+ff ff ff ff ff ff ff ff    ff ff ff ff ff ff ff ff    
+00 1d 02 00 00 00 06 80    0f 03 00 1b 01 
diff --git a/build/checkstyle/checkstyle-checker-api.xml b/build/checkstyle/checkstyle-checker-api.xml
new file mode 100644 (file)
index 0000000..d047405
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+  "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
+  "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
+
+<module name="Checker">
+       <module name="TreeWalker">
+               <module name="JavadocType">
+                       <property name="scope" value="public" />
+                       <property name="allowUnknownTags" value="true" />
+               </module> 
+               <module name="JavadocMethod">
+                       <property name="scope" value="public" />
+                       <property name="allowMissingReturnTag" value="false" />
+                       <property name="allowMissingParamTags" value="false" /> 
+                       <property name="allowMissingThrowsTags" value="false" />        
+                       <property name="allowUndeclaredRTE" value="true"/>
+               </module>
+       </module>
+</module>
\ No newline at end of file
diff --git a/build/checkstyle/checkstyle-checker.xml b/build/checkstyle/checkstyle-checker.xml
new file mode 100644 (file)
index 0000000..ea552e5
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+  "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
+  "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
+
+<module name="Checker">
+       <module name="TreeWalker">
+               <module name="JavadocType">
+                       <property name="scope" value="public" />
+                       <property name="allowUnknownTags" value="true" />
+               </module> 
+       </module>
+</module>
\ No newline at end of file
diff --git a/concepts/.gitignore b/concepts/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/concepts/.project b/concepts/.project
new file mode 100644 (file)
index 0000000..11db21e
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>nps-concepts</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/concepts/bin/.gitignore b/concepts/bin/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/concepts/bin/.project b/concepts/bin/.project
new file mode 100644 (file)
index 0000000..11db21e
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>nps-concepts</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/concepts/bin/pom.xml b/concepts/bin/pom.xml
new file mode 100644 (file)
index 0000000..d9b9622
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>protocol-parent</artifactId>
+               <version>0.1</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>concepts</artifactId>
+       <description>Basic protocol concepts</description>
+       <packaging>bundle</packaging>
+       <version>1.0</version>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>util</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.code.findbugs</groupId>
+                       <artifactId>jsr305</artifactId>
+                       <version>2.0.1</version>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Import-Package>
+                                                       org.opendaylight.protocol.concepts,
+                            org.opendaylight.protocol.util,
+                            com.google.common.base,
+                            com.google.common.collect,
+                            com.google.common.net,
+                            com.google.common.primitives,
+                            com.google.guava;
+                                               </Import-Package>
+                                               <Export-Package>
+                            org.opendaylight.protocol.concepts,
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>${checkstyle.version}</version>
+                               <configuration>
+                                       <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+                                       <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>NPS-CONCEPTS Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/concepts/bin/src/site/apt/index.apt.vm b/concepts/bin/src/site/apt/index.apt.vm
new file mode 100644 (file)
index 0000000..240ca24
--- /dev/null
@@ -0,0 +1,6 @@
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
diff --git a/concepts/bin/src/site/site.xml b/concepts/bin/src/site/site.xml
new file mode 100644 (file)
index 0000000..e468b3b
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+  <body>
+    <head>${project.artifactId}</head>
+    <links>
+      <item name="${project.artifactId}" href="index.html"/>
+    </links>
+
+    <menu ref="parent"/>
+
+    <menu ref="reports"/>
+
+    
+  </body>
+</project>
+
diff --git a/concepts/pom.xml b/concepts/pom.xml
new file mode 100644 (file)
index 0000000..d9b9622
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>protocol-parent</artifactId>
+               <version>0.1</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>concepts</artifactId>
+       <description>Basic protocol concepts</description>
+       <packaging>bundle</packaging>
+       <version>1.0</version>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>util</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.code.findbugs</groupId>
+                       <artifactId>jsr305</artifactId>
+                       <version>2.0.1</version>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Import-Package>
+                                                       org.opendaylight.protocol.concepts,
+                            org.opendaylight.protocol.util,
+                            com.google.common.base,
+                            com.google.common.collect,
+                            com.google.common.net,
+                            com.google.common.primitives,
+                            com.google.guava;
+                                               </Import-Package>
+                                               <Export-Package>
+                            org.opendaylight.protocol.concepts,
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>${checkstyle.version}</version>
+                               <configuration>
+                                       <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+                                       <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>NPS-CONCEPTS Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/ASNumber.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/ASNumber.java
new file mode 100644 (file)
index 0000000..b694d03
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+/**
+ * Autonomous System (AS) Number. This is an Internet-level concept, where each
+ * AS number identifies an administrative domain.
+ * @see <a href="http://en.wikipedia.org/wiki/Autonomous_System_%28Internet%29">Wikipedia article</a>
+ */
+@Immutable
+public final class ASNumber implements Comparable<ASNumber>, Identifier {
+       /**
+        * AS_TRANS as defined by RFC4893 and RFC6793.
+        */
+       public static final ASNumber TRANS = new ASNumber(23456);
+       private static final long serialVersionUID = 7654204313238963136L;
+       private final int highValue, lowValue;
+
+       /**
+        * Create an AS number representation from a pair of 16bit integers,
+        * representing high/low components, for example as carried in ASDOT+
+        * notation.
+        *
+        * @param highValue Value of high-order 16 bits
+        * @param lowValue Value of low-order 16 bits
+        * @throws
+        *     @li IllegalArgumentException when either highValue or lowValue
+        *         out of allowed range (0-65535)
+        */
+       public ASNumber(final int highValue, final int lowValue) {
+               if (highValue < 0 || highValue > 65535)
+                       throw new IllegalArgumentException("Invalid high-order value");
+               if (lowValue < 0 || lowValue > 65535)
+                       throw new IllegalArgumentException("Invalid low-order value");
+
+               this.highValue = highValue;
+               this.lowValue = lowValue;
+       }
+
+       /**
+        * Create an AS number representation from a single integer. The
+        * integer is the 'raw' AS number value, with unsigned 32bit range,
+        * for example as carried in PLAIN notation.
+        *
+        * @param asn Raw AS number
+        * @throws
+        *     @li IllegalArgumentException when asn is out of allowed range
+        *         (0-4294967295)
+        */
+       public ASNumber(final long asn) {
+               if (asn < 0 || asn > 4294967295L)
+                       throw new IllegalArgumentException("Invalid AS number");
+
+               this.highValue = (int) (asn / 65536);
+               this.lowValue = (int) (asn % 65536);
+       }
+
+       /**
+        * Get the AS number as a single integer. For 2-octet AS numbers,
+        * only low 1 bits are used.
+        *
+        * @return Raw AS number
+        */
+       public long getAsn() {
+               return highValue * 65536L + lowValue;
+       }
+
+       /**
+        * Get the high-valued part of the AS number. For 2-octet AS numbers,
+        * this will always be 0.
+        *
+        * @return High-order bits, guaranteed to be in 0-65535 range.
+        */
+       public int getHighValue() {
+               return highValue;
+       }
+
+       /**
+        * Get the low-valued part of the AS number. For 2-octet AS numbers,
+        * this value is equal to the AS number.
+        *
+        * @return Low-order bits, guaranteed to be in 0-65535 range.
+        */
+       public int getLowValue() {
+               return lowValue;
+       }
+
+       @Override
+       public boolean equals(final Object o) {
+               if (!(o instanceof ASNumber))
+                       return false;
+
+               final ASNumber as = (ASNumber)o;
+               return lowValue == as.lowValue && highValue == as.highValue;
+       }
+
+       @Override
+       public int hashCode() {
+               return 7 * lowValue + 13 * highValue;
+       }
+
+       @Override
+       public int compareTo(final ASNumber as) {
+               if (highValue != as.highValue)
+                       return highValue - as.highValue;
+               if (lowValue != as.lowValue)
+                       return lowValue - as.lowValue;
+               return 0;
+       }
+
+       /**
+        * {@inheritDoc}
+        *
+        * Output string is formated according in ASDOT notation.
+        * @see <a href="http://tools.ietf.org/html/rfc5396">RFC5396</a>
+        */
+       @Override
+       public String toString() {
+               final StringBuilder sb = new StringBuilder();
+
+               if (highValue != 0) {
+                       sb.append(highValue);
+                       sb.append('.');
+               }
+               sb.append(lowValue);
+               return sb.toString();
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractAddressFamily.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractAddressFamily.java
new file mode 100644 (file)
index 0000000..d72695a
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.collect.Sets;
+import com.google.common.primitives.UnsignedBytes;
+
+public abstract class AbstractAddressFamily<T extends NetworkAddress<?>> implements AddressFamily<T> {
+       @Override
+       public Set<Prefix<T>> prefixListForBytes(byte[] bytes) {
+               if (bytes.length == 0)
+                       return Collections.emptySet();
+
+               final Set<Prefix<T>> list = Sets.newHashSet();
+               int byteOffset = 0;
+               while (byteOffset < bytes.length) {
+                       final int bitLength = UnsignedBytes.toInt(ByteArray.subByte(bytes, byteOffset, 1)[0]);
+                       byteOffset += 1;
+                       final int byteCount = (bitLength % 8 != 0) ? (bitLength / 8) + 1 : bitLength / 8;
+                       list.add(prefixForBytes(ByteArray.subByte(bytes, byteOffset, byteCount), bitLength));
+                       byteOffset += byteCount;
+               }
+               return list;
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractIdentifier.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractIdentifier.java
new file mode 100644 (file)
index 0000000..c5fa605
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Utility class for implementing identifiers. Subclasses need to provide
+ * a byte[] representation of the encapsulated identifier which is unique
+ * in its domain. This class then implements the required interfaces.
+ *
+ * @param <T> template parameter reference to subclass
+ */
+public abstract class AbstractIdentifier<T extends AbstractIdentifier<?>> implements Comparable<T>, Identifier {
+       private static final long serialVersionUID = 7024836009610553163L;
+
+       /**
+        * Get raw identifier bytes. Override this method to provide the base
+        * class with a raw representation of your identifier. This is then
+        * used in calculations.
+        *
+        * @return Bytearray representation of the identifier
+        */
+       abstract protected byte[] getBytes();
+
+       abstract protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper);
+
+       @Override
+       public int hashCode() {
+               return Arrays.hashCode(this.getBytes());
+       }
+
+       @Override
+       public boolean equals(final Object o) {
+               if (this == o)
+                       return true;
+               if (o == null)
+                       return false;
+
+               if (this.getClass().equals(o.getClass())
+                               && o instanceof AbstractIdentifier<?>)
+                       return Arrays.equals(this.getBytes(),
+                                       ((AbstractIdentifier<?>) o).getBytes());
+               return false;
+       }
+
+       @Override
+       public int compareTo(final T id) {
+               boolean assignable = this.getClass().isAssignableFrom(id.getClass());
+               if (assignable == false) {
+                       throw new IllegalArgumentException("Object " + id + " is not assignable to " + getClass());
+               }
+
+               final byte[] myb = this.getBytes();
+               final byte[] idb = id.getBytes();
+
+               for (int i = 0; i < idb.length && i < myb.length; ++i) {
+                       if (myb[i] != idb[i])
+                               return myb[i] - idb[i];
+               }
+
+               if (idb.length != myb.length)
+                       return myb.length - idb.length;
+
+               return 0;
+       }
+
+       @Override
+       public final String toString() {
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractMetric.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractMetric.java
new file mode 100644 (file)
index 0000000..19f34f6
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.concepts;
+
+/**
+ * Abstract helper class for metrics which are based on integral values,
+ * with numberically lower numbers being considered better candidates.
+ *
+ * @param <T> template reference to subclass
+ */
+public abstract class AbstractMetric<T extends AbstractMetric<?>> implements Metric<T> {
+       private static final long serialVersionUID = 4404624006216930524L;
+       private final long value;
+
+       protected AbstractMetric(final long value) {
+               this.value = value;
+       }
+
+       /**
+        * Get the metric value.
+        *
+        * @return Metric value
+        */
+       public long getValue() {
+               return value;
+       }
+
+       @Override
+       public int compareTo(final T other) {
+               if (value < other.getValue())
+                       return -1;
+               if (value > other.getValue())
+                       return 1;
+               return 0;
+       }
+
+       @Override
+       public final int hashCode() {
+               return (int)value;
+       }
+
+       @Override
+       public final boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (obj.getClass() != this.getClass())
+                       return false;
+               return value == ((AbstractMetric<?>)obj).getValue();
+       }
+
+       @Override
+       public String toString() {
+               return String.valueOf(value);
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractPrefix.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/AbstractPrefix.java
new file mode 100644 (file)
index 0000000..c399661
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+/**
+ * Abstract base class for implementing Prefix classes. This class correctly
+ * implements all required methods, so to implement a Prefix class, you
+ * only need to subclass it and publish an appropriate contructor.
+ *
+ * @param <T> template parameter reference to subclass
+ */
+public abstract class AbstractPrefix<T extends NetworkAddress<T>> implements Comparable<AbstractPrefix<T>>, Prefix<T> {
+
+       private static final long serialVersionUID = -384546010175152481L;
+
+       private final T address;
+       private final int length;
+
+       /**
+        * Create a new prefix object.
+        *
+        * @param address Base network address
+        * @param length Length of significant part of address, in bits
+        */
+       protected AbstractPrefix(final T address, final int length) {
+               this.address = address.applyMask(length);
+               this.length = length;
+       }
+
+       @Override
+       public T getAddress() {
+               return this.address;
+       }
+
+       @Override
+       public int getLength() {
+               return this.length;
+       }
+
+       @Override
+       public int compareTo(final AbstractPrefix<T> p) {
+               final int i = this.address.compareTo(p.getAddress());
+               if (i != 0)
+                       return i;
+               if (this.length < p.getLength())
+                       return -1;
+               if (this.length > p.getLength())
+                       return 1;
+               return 0;
+       }
+
+       @Override
+       public boolean contains(final NetworkAddress<?> address) {
+               /*
+                * Fastest way of checking this is to apply this prefixe's
+                * mask and check for equality.
+                */
+               final NetworkAddress<?> masked = address.applyMask(this.length);
+               return this.address.equals(masked);
+       }
+
+       /**
+        * {@inheritDoc}
+        *
+        * Returned string will be in the CIDR format.
+        */
+       @Override
+       public String toString() {
+               final StringBuilder sb = new StringBuilder(this.address.toString());
+               sb.append('/');
+               sb.append(this.length);
+               return sb.toString();
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final AbstractPrefix<?> other = (AbstractPrefix<?>) obj;
+               if (this.address == null) {
+                       if (other.address != null)
+                               return false;
+               } else if (!this.address.equals(other.address))
+                       return false;
+               if (this.length != other.length)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.address == null) ? 0 : this.address.hashCode());
+               result = prime * result + this.length;
+               return result;
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/AddressFamily.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/AddressFamily.java
new file mode 100644 (file)
index 0000000..973b46a
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.util.Set;
+
+/**
+ * Interface marking an Address Family concept. An address family defines
+ * a NetworkAddress type, corresponding Prefix type as well as their textual
+ * representations.
+ * 
+ * @param <T> Network Address type
+ */
+public interface AddressFamily<T extends NetworkAddress<?>> {
+       /**
+        * Attempt to parse an address from a string. 
+        * 
+        * @param string String representation of the address
+        * @return A network address instance
+        * @throws IllegalArgumentException if string is null or does not conform
+        *         to address encoding rules.
+        */
+       public T addressForString(String string);
+
+       /**
+        * Attempt to parse a parse from a string. 
+        * 
+        * @param string String representation of the prefix
+        * @return A prefix instance
+        * @throws IllegalArgumentException if string is null or does not conform
+        *         to prefix encoding rules.
+        * @throws NumberFormatException if the prefix length is not a parseable
+        *         number.
+        */
+       public Prefix<T> prefixForString(String string);
+
+       /**
+        * Create a network address from a its byte representation.
+        *
+        * @param bytes address as a byte array
+        * @return {@link NetworkAddress}
+        * @throws IllegalArgumentException if the provided byte array
+        *         does not conform to address formatting rules
+        */
+       public T addressForBytes(byte[] bytes);
+
+       /**
+        * Parse a byte array into a Prefix of specified length
+        *
+        * @param bytes array to be parsed to a Prefix
+        * @param bitLength
+        *            length of the prefix in bits, to be given as parameter when
+        *            initializing a Prefix
+        * @return new Prefix
+        */
+       public Prefix<T> prefixForBytes(byte[] bytes, int bitLength);
+
+       /**
+        * Parse given byte array to a list of prefixes.
+        *
+        * @param bytes byte array to be parsed.
+        * @return list of prefixes, if bytes is empty, returns empty list.
+        */
+       public Set<? extends Prefix<T>> prefixListForBytes(byte[] bytes);
+
+       /**
+        * Returns the number of bytes required for successful address
+        * reconstruction via {@link addressForBytes}
+        * 
+        * @return number of bytes required
+        */
+       public int requiredBytes();
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/Bandwidth.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/Bandwidth.java
new file mode 100644 (file)
index 0000000..d1cd6f3
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.io.Serializable;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Bandwidth concept class. It represents network bandwidth in bytes per second.
+ * The precision of this class is limited to single-precision floating-point.
+ */
+@Immutable
+public final class Bandwidth implements Comparable<Bandwidth>, Serializable {
+       public static final Bandwidth ZERO = new Bandwidth(0);
+       private static final long serialVersionUID = 5795612451568505103L;
+       private final double bytesPerSecond;
+
+       /**
+        * Constructor of {@link Bandwidth} object.
+        * @param bytesPerSecond Bandwidth capacity, expressed as bytes per second
+        */
+       public Bandwidth(final double bytesPerSecond) {
+               this.bytesPerSecond = bytesPerSecond;
+       }
+
+       /**
+        * Standard getter for bytesPerSecond attribute of {@link Bandwidth}.
+        * @return bytesPerSecond Bandwidth capacity, expressed as bytes per second
+        */
+       public double getBytesPerSecond() {
+               return bytesPerSecond;
+       }
+
+       /**
+        * Standard getter for bitsPerSecond attribute of {@link Bandwidth}.
+        * @return bitsPerSecond Bandwidth capacity, expressed as bytes per second
+        */
+       public long getBitsPerSecond() {
+               return (long) (8 * bytesPerSecond);
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               long temp;
+               temp = Double.doubleToLongBits(bytesPerSecond);
+               result = prime * result + (int) (temp ^ (temp >>> 32));
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               Bandwidth other = (Bandwidth) obj;
+               if (Double.doubleToLongBits(bytesPerSecond) != Double
+                               .doubleToLongBits(other.bytesPerSecond))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public int compareTo(final Bandwidth b) {
+               if (bytesPerSecond < b.bytesPerSecond)
+                       return -1;
+               if (bytesPerSecond > b.bytesPerSecond)
+                       return 1;
+               return 0;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder sb = new StringBuilder("Bandwidth [bytesPerSecond=");
+               sb.append(bytesPerSecond);
+               sb.append(']');
+               return sb.toString();
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/IGPMetric.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/IGPMetric.java
new file mode 100644 (file)
index 0000000..48eedb7
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+/**
+ * Interior Gateway Protocol metric class.
+ */
+public final class IGPMetric extends AbstractMetric<IGPMetric> {
+       private static final long serialVersionUID = -401875021705133799L;
+
+       /**
+        * Construct a new IGP metric object.
+        *
+        * @param value Metric value
+        * @throws IllegalArgumentException ex when value is outside of allowed
+        *         range (0-16777215)
+        */
+       public IGPMetric(final long value) {
+               super(value);
+               if (value < 0 || value > 16777215)
+                       throw new IllegalArgumentException("Invalid IGP metric value");
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/IPAddresses.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/IPAddresses.java
new file mode 100644 (file)
index 0000000..6e51e42
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.protocol.concepts.AddressFamily;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.net.InetAddresses;
+
+/**
+ * Utility class for dealing with various IP-based network addresses.
+ */
+public final class IPAddresses {
+       /**
+        * A set containing all IP address families.
+        */
+       public static final Set<AddressFamily<?>> FAMILIES;
+
+       static {
+               FAMILIES = new HashSet<>(2);
+               FAMILIES.add(IPv4.FAMILY);
+               FAMILIES.add(IPv6.FAMILY);
+       }
+
+       private IPAddresses() { }
+
+       /**
+        * Instantiate a network address from its string representation.
+        *
+        * @param string string representation
+        * @return network address parsed from the string
+        * @throws IllegalArgumentException if the string failed to parse
+        *         into any of the supported classes.
+        */
+       public static NetworkAddress<?> parseNetworkAddress(final String string) {
+               final InetAddress a = InetAddresses.forString(string);
+               if (a instanceof Inet4Address)
+                       return new IPv4Address(a);
+               if (a instanceof Inet6Address)
+                       return new IPv6Address(a);
+               throw new IllegalArgumentException("Unsupported network address");
+       }
+
+       public static NetworkAddress<?> createNetworkAddress(InetAddress inetAddress) {
+               checkNotNull(inetAddress);
+               if (inetAddress instanceof Inet4Address) {
+                       return new IPv4Address(inetAddress);
+               } else if (inetAddress instanceof Inet6Address) {
+                       return new IPv6Address(inetAddress);
+               } else {
+                       throw new IllegalStateException("Unknown InetAddress " + inetAddress);
+               }
+       }
+}
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv4.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv4.java
new file mode 100644 (file)
index 0000000..0d53657
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Preconditions;
+import com.google.common.net.InetAddresses;
+
+public final class IPv4 extends AbstractAddressFamily<IPv4Address> {
+       private static final Pattern regex = Pattern.compile("/");
+       public static final Set<AddressFamily<?>> FAMILIES;
+       public static final IPv4 FAMILY;
+
+       static {
+               FAMILY = new IPv4();
+               FAMILIES = new HashSet<>(1);
+               FAMILIES.add(FAMILY);
+       }
+
+       private IPv4() { }
+
+       @Override
+       public IPv4Address addressForString(final String string) {
+               Preconditions.checkNotNull(string, "String may not be null");
+               return new IPv4Address(InetAddresses.forString(string));
+       }
+
+       @Override
+       public IPv4Prefix prefixForString(final String string) {
+               Preconditions.checkNotNull(string, "String may not be null");
+
+               final String[] strs = regex.split(string);
+               Preconditions.checkArgument(strs.length == 2, "Malformed prefix string");
+               final byte len = Byte.valueOf(strs[1]);
+               Preconditions.checkArgument(len >= 0 && len <= 32, "Prefix length has to be in range 0-32");
+               return addressForString(strs[0]).asPrefix(len);
+       }
+
+       @Override
+       public IPv4Address addressForBytes(byte[] bytes) {
+               return new IPv4Address(bytes);
+       }
+
+       @Override
+       public int requiredBytes() {
+               return 4;
+       }
+
+       @Override
+       public IPv4Prefix prefixForBytes(byte[] bytes, int bitLength) {
+               Preconditions.checkArgument(bytes.length <= 4, "Byte array too large");
+               Preconditions.checkArgument(bitLength <= 32, "Bitlength too large");
+
+               if (bytes.length != 4)
+                       bytes = Arrays.copyOf(bytes, 4);
+
+               return addressForBytes(bytes).asPrefix(bitLength);
+       }
+}
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv4Address.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv4Address.java
new file mode 100644 (file)
index 0000000..2c3ae5d
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Preconditions;
+
+/**
+ * This class represents an IPv4 address. This is the well-known 4-byte address
+ * used all over the Internet. The difference between this class and the
+ * readily-available Inet4Address is the fact it is derived from a well-known
+ * concept and it is a pure data holder.
+ */
+public class IPv4Address implements NetworkAddress<IPv4Address> {
+       private static final long serialVersionUID = -5856802567090053919L;
+       private final byte[] bytes;
+
+       /**
+        * Instantiate a new IPv4Address based on raw byte representation.
+        *
+        * @param bytes Bytearray holding the byte representation
+        * @throws
+        * @li IllegalArgumentException when length of bytes is not 4
+        */
+       public IPv4Address(final byte[] bytes) {
+               Preconditions.checkNotNull(bytes);
+               Preconditions.checkArgument(bytes.length == 4);
+               this.bytes = bytes;
+       }
+
+       /**
+        * Instantiate a new IPv4Address based on the contents of a Inet4Address.
+        *
+        * @param address
+        *            IPv4 address in Inet4Address format
+        * @throws
+        * @li IllegalArgumentException when address is not in Inet4Address format
+        */
+       public IPv4Address(final InetAddress address) {
+               if (!(address instanceof Inet4Address))
+                       throw new IllegalArgumentException(
+                                       "This class can only handle IPv4 addresses");
+               this.bytes = address.getAddress();
+       }
+
+       @Override
+       public boolean equals(final Object o) {
+               return o instanceof IPv4Address
+                               && Arrays.equals(this.bytes, ((IPv4Address) o).bytes);
+       }
+
+       @Override
+       public int hashCode() {
+               return Arrays.hashCode(this.bytes);
+       }
+
+       @Override
+       public byte[] getAddress() {
+               return this.bytes;
+       }
+
+       @Override
+       public int compareTo(final IPv4Address addr) {
+               for (int i = 0; i < this.bytes.length; ++i) {
+                       if (this.bytes[i] != addr.bytes[i]) {
+                               int i1 = 0, i2 = 0;
+                               i1 = this.bytes[i] < 0 ? this.bytes[i] + 256 : this.bytes[i];
+                               i2 = addr.bytes[i] < 0 ? addr.bytes[i] + 256 : addr.bytes[i];
+                               return i1 - i2;
+                       }
+               }
+               return 0;
+       }
+
+       /**
+        * {@inheritDoc}
+        *
+        * Output string is formated according to InetAddress formatting rules.
+        */
+       @Override
+       public String toString() {
+               try {
+                       return InetAddress.getByAddress(Arrays.copyOf(this.bytes, 4))
+                                       .getHostAddress();
+               } catch (final UnknownHostException e) {
+                       throw new RuntimeException("Unexpected malformed address", e);
+               }
+       }
+
+       @Override
+       public IPv4Address applyMask(final int bits) {
+               if (bits < 0 || bits > 32)
+                       throw new IllegalArgumentException("Bit length has to be in range 0-32");
+               return new IPv4Address(ByteArray.maskBytes(this.bytes, bits));
+       }
+
+       @Override
+       public IPv4Prefix asPrefix(int length) {
+               return new IPv4Prefix(this, length);
+       }
+
+       @Override
+       public IPv4Prefix asHostPrefix() {
+               return asPrefix(32);
+       }
+
+       @Override
+       public IPv4 getAddressFamily() {
+               return IPv4.FAMILY;
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv4Prefix.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv4Prefix.java
new file mode 100644 (file)
index 0000000..d03b9aa
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+/**
+ * IPv4 Address prefix.
+ */
+public class IPv4Prefix extends AbstractPrefix<IPv4Address> {
+
+       private static final long serialVersionUID = 2206353300109616995L;
+
+       /**
+        * Construct an IPv4 prefix given a base IPv4 address and prefix
+        * length.
+        *
+        * @param address Base address
+        * @param length Prefix length, as to be between 0-32.
+        */
+       public IPv4Prefix(final IPv4Address address, final int length) {
+               super(address, length);
+       }
+
+       @Override
+       public IPv4 getAddressFamily() {
+               return IPv4.FAMILY;
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv6.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv6.java
new file mode 100644 (file)
index 0000000..926360b
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Preconditions;
+import com.google.common.net.InetAddresses;
+
+public final class IPv6 extends AbstractAddressFamily<IPv6Address> {
+       private static final Pattern regex = Pattern.compile("/");
+       public static final Set<AddressFamily<?>> FAMILIES;
+       public static final IPv6 FAMILY;
+
+       static {
+               FAMILY = new IPv6();
+               FAMILIES = new HashSet<>(1);
+               FAMILIES.add(FAMILY);
+       }
+
+       private IPv6() { }
+
+       @Override
+       public IPv6Address addressForString(final String string) {
+               Preconditions.checkNotNull(string, "String may not be null");
+               return new IPv6Address(InetAddresses.forString(string));
+       }
+
+       @Override
+       public IPv6Prefix prefixForString(final String string) {
+               Preconditions.checkNotNull(string, "String may not be null");
+
+               final String[] strs = regex.split(string);
+               final byte len = Byte.valueOf(strs[1]);
+               Preconditions.checkArgument(len >= 0 && len <= 128, "Prefix length has to be in range 0-128");
+               return addressForString(strs[0]).asPrefix(len);
+       }
+
+       @Override
+       public IPv6Address addressForBytes(byte[] bytes) {
+               return new IPv6Address(bytes);
+       }
+
+       @Override
+       public int requiredBytes() {
+               return 16;
+       }
+
+       @Override
+       public IPv6Prefix prefixForBytes(byte[] bytes, int bitLength) {
+               Preconditions.checkArgument(bytes.length <= 16, "Byte array too large");
+               Preconditions.checkArgument(bitLength <= 128, "Bitlength too large");
+
+               if (bytes.length != 16)
+                       bytes = Arrays.copyOf(bytes, 16);
+
+               return addressForBytes(bytes).asPrefix(bitLength);
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv6Address.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv6Address.java
new file mode 100644 (file)
index 0000000..bbb51ce
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Preconditions;
+
+/**
+ * This class represents an IPv6 address. This is the well-known 16-byte address
+ * used all over the Internet. The difference between this class and the
+ * readily-available Inet6Address is the fact it is derived from a well-known
+ * concept and it is a pure data holder.
+ */
+public class IPv6Address implements NetworkAddress<IPv6Address> {
+       private static final long serialVersionUID = 8627230318476805811L;
+       private final byte[] bytes;
+
+       /**
+        * Instantiate a new IPv6Address based on raw byte representation.
+        *
+        * @param bytes Bytearray holding the byte representation
+        * @throws
+        * @li IllegalArgumentException when length of bytes is not 16
+        */
+       public IPv6Address(final byte[] bytes) {
+               Preconditions.checkNotNull(bytes);
+               Preconditions.checkArgument(bytes.length == 16);
+               this.bytes = bytes;
+       }
+
+       /**
+        * Instantiate a new IPv6Address based on the contents of a Inet6Address.
+        *
+        * @param address
+        *            IPv6 address in Inet6Address format
+        * @throws
+        * @li IllegalArgumentException when address is not in Inet6Address format
+        */
+       public IPv6Address(final InetAddress address) {
+               if (!(address instanceof Inet6Address))
+                       throw new IllegalArgumentException(
+                                       "This class can only handle IPv6 addresses");
+               this.bytes = address.getAddress();
+       }
+
+       @Override
+       public boolean equals(final Object o) {
+               return o instanceof IPv6Address
+                               && Arrays.equals(this.bytes, ((IPv6Address) o).bytes);
+       }
+
+       @Override
+       public int hashCode() {
+               return Arrays.hashCode(this.bytes);
+       }
+
+       @Override
+       public byte[] getAddress() {
+               return this.bytes;
+       }
+
+       @Override
+       public int compareTo(final IPv6Address addr) {
+               for (int i = 0; i < this.bytes.length; ++i) {
+                       if (this.bytes[i] != addr.bytes[i]) {
+                               int i1 = 0, i2 = 0;
+                               i1 = this.bytes[i] < 0 ? this.bytes[i] + 256 : this.bytes[i];
+                               i2 = addr.bytes[i] < 0 ? addr.bytes[i] + 256 : addr.bytes[i];
+                               return i1 - i2;
+                       }
+               }
+               return 0;
+       }
+
+       /**
+        * {@inheritDoc}
+        *
+        * Output string is formated according to InetAddress formatting rules.
+        */
+       @Override
+       public String toString() {
+               try {
+                       return InetAddress.getByAddress(Arrays.copyOf(this.bytes, 16))
+                                       .getHostAddress();
+               } catch (final UnknownHostException e) {
+                       throw new RuntimeException("Unexpected malformed address", e);
+               }
+       }
+
+       @Override
+       public IPv6Address applyMask(final int bits) {
+               if (bits < 0 || bits > 128)
+                       throw new IllegalArgumentException("Bit length has to be in range 0-128");
+               return new IPv6Address(ByteArray.maskBytes(this.bytes, bits));
+       }
+
+       @Override
+       public IPv6Prefix asPrefix(int length) {
+               return new IPv6Prefix(this, length);
+       }
+
+       @Override
+       public IPv6Prefix asHostPrefix() {
+               return asPrefix(128);
+       }
+
+       @Override
+       public IPv6 getAddressFamily() {
+               return IPv6.FAMILY;
+       }
+}
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv6Prefix.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/IPv6Prefix.java
new file mode 100644 (file)
index 0000000..03a5263
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * IPv6 Address prefix.
+ */
+@Immutable
+public class IPv6Prefix extends AbstractPrefix<IPv6Address> {
+       private static final long serialVersionUID = 8936908223539148352L;
+
+       /**
+        * Create a new IPv6 prefix using an IPv6 address and prefix
+        * length.
+        *
+        * @param address IPv6 address {@link IPv6Address}
+        * @param length Prefix length
+        */
+       public IPv6Prefix(final IPv6Address address, final int length) {
+               super(address, length);
+       }
+
+       @Override
+       public IPv6 getAddressFamily() {
+               return IPv6.FAMILY;
+       }
+}
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/ISOSystemIdentifier.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/ISOSystemIdentifier.java
new file mode 100644 (file)
index 0000000..77a5f0e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Object representing an ISO System identifier. It is the 6-byte system ID portion of the IS-IS network service access
+ * point (NSAP).
+ */
+public final class ISOSystemIdentifier extends AbstractIdentifier<ISOSystemIdentifier> {
+       private static final long serialVersionUID = 4493531385611530076L;
+       private final byte[] systemId;
+
+       /**
+        * Initialize a new ISO system identifier.
+        * 
+        * @param systemId 6-byte identifier
+        * @throws
+        * @li IllegalArgumentException if the length of supplied systemId is not 6 bytes
+        */
+       public ISOSystemIdentifier(final byte[] systemId) {
+               if (systemId.length != 6)
+                       throw new IllegalArgumentException("Invalid ISO System ID");
+               this.systemId = systemId;
+       }
+
+       @Override
+       public byte[] getBytes() {
+               return this.systemId;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("id", ByteArray.toHexString(this.systemId, "."));
+       }
+}
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/Identifier.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/Identifier.java
new file mode 100644 (file)
index 0000000..bbaffd7
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.io.Serializable;
+
+/**
+ * General identifier interface. It is primarily a marker for all things that
+ * identify concepts -- such as names, addresses, classes, etc. We do not
+ * require too much, just that the identifiers are serializable (and this
+ * transferable).
+ */
+public interface Identifier extends Serializable {
+
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/Immutable.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/Immutable.java
new file mode 100644 (file)
index 0000000..d6c7030
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+/**
+ * Marker interface for objects which are immutable. This interface should be used directly on objects, preferably
+ * final, which are eligible for the JSR-305 @Immutable annotation and objects implementing this interface are required
+ * to abide to interface contract specified by @Immutable. The reason for the existence of this interface is twofold:
+ * unlike @Immutable, it is visible at runtime and objects can be quickly checked for compliance using a quick
+ * 'instanceof' check. This is useful for code which needs to capture a point-in-time snapshot of otherwise unknown
+ * objects -- a typical example being logging/tracing systems. Such systems would normally have to rely on serializing
+ * the object to get a stable checkpoint. Objects marked with this interface are guaranteed to remain stable, thus
+ * already being a checkpoint for all intents and purposes, so aside from retaining a reference no further action on
+ * them is necessary.
+ */
+public interface Immutable {
+
+}
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/InitialListenerEvents.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/InitialListenerEvents.java
new file mode 100644 (file)
index 0000000..1564550
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.util.EventListener;
+import java.util.List;
+
+public final class InitialListenerEvents<L extends EventListener, E> {
+       private final ListenerRegistration<L> registration;
+       private final List<E> events;
+
+       public InitialListenerEvents(final ListenerRegistration<L> registration, final List<E> events) {
+               super();
+               if (registration == null)
+                       throw new NullPointerException("Registration is mandatory!");
+               this.registration = registration;
+               if (events == null)
+                       throw new NullPointerException("Events are mandatory!");
+               this.events = events;
+       }
+
+       /**
+        * @return the registration
+        */
+       public ListenerRegistration<L> getRegistration() {
+               return this.registration;
+       }
+
+       /**
+        * @return the events
+        */
+       public List<E> getEvents() {
+               return this.events;
+       }
+}
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/ListenerRegistration.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/ListenerRegistration.java
new file mode 100644 (file)
index 0000000..7cf59b8
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.io.Closeable;
+import java.util.EventListener;
+
+/**
+ * An interface representing a listener registration. Objects offering
+ * the ability to register listener should return an implementation of this
+ * interface upon successful registration. The users are required to call
+ * #close() before losing the reference to that object.
+ *
+ * @param <T> template reference to associated EventListener implementation
+ */
+public interface ListenerRegistration<T extends EventListener> extends Closeable {
+       /**
+        * Access the listener object associated with this registration.
+        *
+        * @return Associated listener.
+        */
+       public T getListener();
+
+       @Override
+       public void close();
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/Metric.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/Metric.java
new file mode 100644 (file)
index 0000000..2156afa
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.concepts;
+
+import java.io.Serializable;
+
+/**
+ * Interface defining the concept of a metric. Metrics are something which
+ * defines preference of an object when used in a certain context. In that
+ * sense we define total ordering of metrics in the same class.
+ *
+ * @param <T> subtype of Metric
+ */
+public interface Metric<T extends Metric<?>> extends Comparable<T>, Serializable {
+       /**
+        * {@inheritDoc}
+        *
+        * Metrics which compare as 'lower' using this method are to be
+        * considered better candidates than the other metric.
+        */
+       @Override
+       public int compareTo(T o);
+
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/NamedObject.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/NamedObject.java
new file mode 100644 (file)
index 0000000..c403e19
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+/**
+ * General interface for identifyiable objects. Useful when you have an object
+ * which has a sense of identity -- by having a "name".
+ *
+ * @param <T> template reference to the object name's Identifier class
+ */
+public interface NamedObject<T extends Identifier> {
+       /**
+        * Get the object's Identifier (or "name"). A name uniquely identifies
+        * an object among its peers. Two named objects can have the same
+        * identifier, but need not necessarily be equal.
+        *
+        * @return The object's identifier
+        */
+       public T getName();
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/NetworkAddress.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/NetworkAddress.java
new file mode 100644 (file)
index 0000000..ec534bb
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+/**
+ * Generic identifier of a network entity. A network entity is typically a
+ * host. Hosts may be contained within a network -- which is represented by
+ * a @sa Prefix. To support operation within the context of a prefix,
+ * NetworkAddresses have to support a concept of 'masking', where all bits
+ * beyond first <n> bit are set to 0 and any bytes are trimmed.
+ *
+ * @param <T> subtype of Network Address
+ */
+public interface NetworkAddress<T extends NetworkAddress<?>> extends Comparable<T>, Identifier {
+       /**
+        * Returns the raw address of this object. The result is in network
+        * byte order: the highest order byte of the address is in
+        * getAddress()[0].
+        * 
+        * @return the raw address of this object, guaranteed to be non-null
+        */
+       public byte[] getAddress();
+
+       /**
+        * Apply a mask of first #bits, setting the rest to zero.
+        *
+        * @param bits Number of bits to keep in place. Has to be
+        *                 non-negative.
+        * @return A new NetworkAddress instance.
+        */
+       public T applyMask(int bits);
+
+       /**
+        * Convert the address into a prefix of specified length.
+        *
+        * @param length Prefix length
+        * @return A prefix representation of this address.
+        */
+       public Prefix<T> asPrefix(int length);
+
+       /**
+        * Convert the address into a host prefix, e.g. a prefix with length
+        * equal to the address bitsize.
+        *
+        * @return A prefix representation of this address.
+        */
+       public Prefix<T> asHostPrefix();
+
+       /**
+        * Returns the address family class.
+        * 
+        * @return address family class
+        */
+       public AddressFamily<T> getAddressFamily();
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/Prefix.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/Prefix.java
new file mode 100644 (file)
index 0000000..87d8524
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+/**
+ * A network prefix object. Prefix is a networking concept grouping together
+ * a set of addresses into a 'subnet', such that their attributes can be easily
+ * expressed. A prefix is formed by a base NetworkAddress and number of leading
+ * bits which are considered significant. An address is considered to be a part
+ * of a prefix if it differes only in insignificant (right-most) bits.
+ *
+ * @param <T> template reference to a Network Address class
+ */
+public interface Prefix<T extends NetworkAddress<?>> extends Identifier {
+       /**
+        * Get the base address of the prefix.
+        *
+        * @return Base network address
+        */
+       public T getAddress();
+
+       /**
+        * The the length of significant part of the base address.
+        *
+        * @return Prefix length
+        */
+       public int getLength();
+
+       /**
+        * Check if a Prefix contains a particular network address.
+        *
+        * @param address Network address to check for membership
+        * @return true if address belongs to this subnet, false otherwise
+        */
+       public boolean contains(NetworkAddress<?> address);
+
+       /**
+        * Returns the address family class.
+        * 
+        * @return address family class
+        */
+       public AddressFamily<T> getAddressFamily();
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/SharedRiskLinkGroup.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/SharedRiskLinkGroup.java
new file mode 100644 (file)
index 0000000..36aa72f
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+
+/**
+ * Class representing a Shared Risk Link Group identifier. A link may be
+ * part of multiple such groups. Membership in such a group indicates that
+ * members share a common risk (such as single wire, etc.).
+ */
+public class SharedRiskLinkGroup implements Comparable<SharedRiskLinkGroup>, Identifier {
+       private static final long serialVersionUID = -760766663668819360L;
+       private final long value;
+
+       /**
+        * Create a new group with a particular value. Valid values are in
+        * the range of 0-4294967295. Two groups with the same value are
+        * considered equal.
+        * @param value SRLG value
+        */
+       public SharedRiskLinkGroup(final long value) {
+               if (value < 0 || value > 4294967295L)
+                       throw new IllegalArgumentException("Invalid SRLG value");
+               this.value = value;
+       }
+
+       /**
+        * Returns value attribute of {@link SharedRiskLinkGroup}.
+        * @return value of {@link SharedRiskLinkGroup}
+        */
+       public long getValue() {
+               return value;
+       }
+
+       @Override
+       public int compareTo(final SharedRiskLinkGroup other) {
+               if (value < other.value)
+                       return -1;
+               if (value > other.value)
+                       return 1;
+               return 0;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (int) (value ^ (value >>> 32));
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof SharedRiskLinkGroup))
+                       return false;
+               final SharedRiskLinkGroup other = (SharedRiskLinkGroup) obj;
+               if (value != other.value)
+                       return false;
+               return true;
+       }
+}
+
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/State.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/State.java
new file mode 100644 (file)
index 0000000..404e01d
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import java.io.Serializable;
+
+/**
+ * Interface identifying a piece of state information. Implementations of this interface are required to be immutable.
+ * It is also recommended for the projects to be eligible (and carry) the @Immutable JSR-305 annotation.
+ */
+public interface State extends Immutable, Serializable {
+       /**
+        * Report a string representation of the state. The interface contract of this method, unlike its normal Object
+        * ancestor, its return value must be consistent with the equals() method, such that the following always holds:
+        * 
+        * o1.toString().equals(o2.toString()) == o1.equals(o2)
+        * 
+        * @return String representation of the state information
+        */
+       @Override
+       public String toString();
+}
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/Stateful.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/Stateful.java
new file mode 100644 (file)
index 0000000..0e0bdb3
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+/**
+ * Interface marking object which hold some state, which can be captured and saved. Capturing this state is useful for
+ * various entities which need to see a consistent, point-in-time view of the state.
+ * 
+ * @param <T> Type reference of the returned state object
+ */
+public interface Stateful<T extends State> {
+       /**
+        * Return a reference to the current state of the object. The returned object must remain immutable throughout its
+        * lifetime. Furthermore using equals() on two state objects returned from this method must return true if and only
+        * if the internal state of this object the the two points was equivalent.
+        * 
+        * @return Reference to a point-in-time consistent state of the object.
+        */
+       public T currentState();
+}
diff --git a/concepts/src/main/java/org/opendaylight/protocol/concepts/TEMetric.java b/concepts/src/main/java/org/opendaylight/protocol/concepts/TEMetric.java
new file mode 100644 (file)
index 0000000..4c08dd4
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Traffic Engineering metric class.
+ */
+@Immutable
+public final class TEMetric extends AbstractMetric<TEMetric> {
+       private static final long serialVersionUID = -6843828299489991771L;
+
+       /**
+        * Construct a new TE metric object.
+        *
+        * @param value Metric value
+        * @throws IllegalArgumentException ex when value is outside of allowed
+        *         range (0-4294967295)
+        */
+       public TEMetric(final long value) {
+               super(value);
+               if (value < 0 || value > 4294967295L)
+                       throw new IllegalArgumentException("Invalid TE metric value");
+       }
+}
+
diff --git a/concepts/src/site/apt/index.apt.vm b/concepts/src/site/apt/index.apt.vm
new file mode 100644 (file)
index 0000000..240ca24
--- /dev/null
@@ -0,0 +1,6 @@
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
diff --git a/concepts/src/site/site.xml b/concepts/src/site/site.xml
new file mode 100644 (file)
index 0000000..e468b3b
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+  <body>
+    <head>${project.artifactId}</head>
+    <links>
+      <item name="${project.artifactId}" href="index.html"/>
+    </links>
+
+    <menu ref="parent"/>
+
+    <menu ref="reports"/>
+
+    
+  </body>
+</project>
+
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/ASNumberTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/ASNumberTest.java
new file mode 100644 (file)
index 0000000..6513e6c
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.concepts;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class ASNumberTest {
+       private ASNumber asn1, asn2, asn3, asn4;
+
+       @Before
+       public void setUp() {
+               asn1 = new ASNumber(100, 200);
+               asn2 = new ASNumber(6553800);
+               asn3 = new ASNumber(0, 200);
+               asn4 = new ASNumber(100, 199);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testHighValueUnderflow() {
+               new ASNumber(-1, 0);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testHighValueOverflow() {
+               new ASNumber(65536, 0);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testLowValueUnderflow() {
+               new ASNumber(0, -1);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testLowValueOverflow() {
+               new ASNumber(0, 65536);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testAsnUnderflow() {
+               new ASNumber(0, -1);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testAsnOverflow() {
+               new ASNumber(4294967296L);
+       }
+
+       @Test
+       public void testHashCode() {
+               final Set<ASNumber> set = new HashSet<ASNumber>();
+
+               set.add(asn1);
+               assertEquals(1, set.size());
+
+               set.add(asn2);
+               assertEquals(1, set.size());
+
+               set.add(asn3);
+               assertEquals(2, set.size());
+       }
+
+       @Test
+       public void testCompareTo() {
+               final Set<ASNumber> set = new TreeSet<ASNumber>();
+
+               set.add(asn1);
+               assertEquals(1, set.size());
+
+               set.add(asn2);
+               assertEquals(1, set.size());
+
+               set.add(asn3);
+               assertEquals(2, set.size());
+
+               set.add(asn4);
+               assertEquals(3, set.size());
+       }
+
+       @Test
+       public void testGetters() {
+               assertEquals(100, asn1.getHighValue());
+               assertEquals(200, asn1.getLowValue());
+               assertEquals(6553800, asn1.getAsn());
+       }
+
+       @Test
+       public void testEquals() {
+               assertThat(asn1, equalTo(asn2));
+               assertThat(asn1, not(equalTo(asn3)));
+               assertThat(asn1, not(equalTo(asn4)));
+               assertThat(asn1, not(equalTo(new Object())));
+               assertFalse(asn1.equals(new Object()));
+       }
+
+       @Test
+       public void testToString() {
+               assertEquals("100.200", asn1.toString());
+               assertEquals("200", asn3.toString());
+       }
+}
+
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/AbstractIdentifierTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/AbstractIdentifierTest.java
new file mode 100644 (file)
index 0000000..068567e
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+public class AbstractIdentifierTest {
+
+       private class AbstractIdentifierT extends AbstractIdentifier<AbstractIdentifierT> {
+
+               private static final long serialVersionUID = 3803643153695225193L;
+
+               public byte[] bytes;
+
+               public AbstractIdentifierT(final byte[] bytes) {
+                       this.bytes = bytes;
+               }
+
+               @Override
+               protected byte[] getBytes() {
+                       return this.bytes;
+               }
+
+               @Override
+               protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+                       return toStringHelper.add("bytes", ByteArray.toHexString(bytes, "."));
+               }
+       }
+
+       @Test
+       public void testToString() {
+               final AbstractIdentifier<AbstractIdentifierT> ai = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 168, 31, 8});
+
+               assertEquals("AbstractIdentifierT{bytes=ac.a8.1f.08}", ai.toString());
+       }
+
+
+       @Test
+       public void testCompareTo() {
+               final AbstractIdentifier<AbstractIdentifierT> a1 = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 168, 31, 8});
+               final AbstractIdentifier<AbstractIdentifierT> a2 = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 167, 31, 8});
+               final AbstractIdentifier<AbstractIdentifierT> a4 = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 167});
+
+               assertEquals(0, a1.compareTo((AbstractIdentifierT) a1));
+               assertEquals(-1, a2.compareTo((AbstractIdentifierT) a1));
+               assertEquals(1, a1.compareTo((AbstractIdentifierT) a2));
+
+               final AbstractIdentifier<AbstractIdentifier<?>> a3 = new AbstractIdentifier<AbstractIdentifier<?>>() {
+
+                       private static final long serialVersionUID = 1L;
+
+                       @Override
+                       protected byte[] getBytes() {
+                               return null;
+                       }
+
+                       @Override
+                       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+                               return toStringHelper;
+                       }
+               };
+
+               try {
+                       a3.compareTo(a1);
+                       fail("Exception should have occured.");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Object " + a1 + " is not assignable to " + a3.getClass() , e.getMessage());
+               }
+
+               assertEquals(2, a2.compareTo((AbstractIdentifierT) a4));
+       }
+
+       @Test
+       public void testHashCodeEquals() {
+               final AbstractIdentifier<AbstractIdentifierT> a1 = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 168, 31, 8});
+               final AbstractIdentifier<AbstractIdentifierT> a2 = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 167, 31, 8});
+
+               assertNotSame(a1.hashCode(), a2.hashCode());
+               assertFalse(a1.equals(a2));
+               assertEquals(a1, a1);
+       }
+}
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/AddressFamiliesTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/AddressFamiliesTest.java
new file mode 100644 (file)
index 0000000..329d0b9
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Test;
+
+public class AddressFamiliesTest {
+       @Test
+       public void testParseIpv4Prefix() throws UnknownHostException {
+               final byte[] pref = new byte[] { (byte) 172, 17, 2 };
+               final Prefix<?> after = IPv4.FAMILY.prefixForBytes(pref, 24);
+               final Prefix<IPv4Address> expected = new IPv4Prefix(new IPv4Address(InetAddress.getByName("172.17.2.0")), 24);
+               assertEquals(expected, after);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testParseIpv4Prefix2(){
+               IPv4.FAMILY.prefixForBytes(new byte[5], 20);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testParseIpv4Prefix3(){
+               IPv4.FAMILY.prefixForBytes(new byte[] { (byte) 172, 17, 2 }, 33);
+       }
+
+       @Test
+       public void testParseIpv6Prefix() throws UnknownHostException {
+               final byte[] pref = new byte[] { (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x02 };
+               final Prefix<?> after =IPv6.FAMILY.prefixForBytes(pref, 64);
+               final Prefix<IPv6Address> expected = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:1:2::")), 64);
+               assertEquals(expected, after);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testParseIpv6Prefix2(){
+               IPv4.FAMILY.prefixForBytes(new byte[17], 30);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testParseIpv6Prefix3(){
+               IPv4.FAMILY.prefixForBytes(new byte[] { (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x02 }, 129);
+       }
+
+       @Test
+       public void testParseIpv6PrefixList(){
+               assertTrue(IPv6.FAMILY.prefixListForBytes(new byte[0]).isEmpty());
+       }
+
+       @Test
+       public void testParseIpv6PrefixList2(){
+               assertEquals(2, IPv6.FAMILY.prefixListForBytes(new byte[] { (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, (byte) 0x00, (byte) 0x01, (byte) 0x00, }).size());
+       }
+
+       @Test
+       public void testParseIpv4PrefixList(){
+               assertTrue(IPv4.FAMILY.prefixListForBytes(new byte[0]).isEmpty());
+       }
+
+       @Test
+       public void testParseIpv4PrefixList2(){
+               assertFalse(IPv4.FAMILY.prefixListForBytes(new byte[] { (byte) 15, 17, 2 }).isEmpty());
+       }
+}
+
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/BandwidthTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/BandwidthTest.java
new file mode 100644 (file)
index 0000000..dcb98e7
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.concepts;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class BandwidthTest {
+       private Bandwidth b1, b2, b3, b4;
+
+       @Before
+       public void setUp() {
+               b1 = new Bandwidth(1000);
+               b2 = new Bandwidth(2000);
+               b3 = new Bandwidth(2000);
+               b4 = new Bandwidth(100);
+       }
+
+       @Test
+       public void testBitsBytes() {
+               assertEquals(8000, b1.getBitsPerSecond());
+               assertEquals(1000.0, b1.getBytesPerSecond(), 0.1);
+       }
+
+       @Test
+       public void testEquals() {
+               assertFalse(b1.equals(null));
+               assertThat(b1, not(equalTo(new Object())));
+               assertThat(b1, equalTo(b1));
+               assertThat(b1, not(equalTo(b2)));
+               assertThat(b2, equalTo(b3));
+               assertFalse(b1.equals(new Object()));
+       }
+
+       @Test
+       public void testToString(){
+               String s1 = "Bandwidth [bytesPerSecond=" + b1.getBytesPerSecond() + "]";
+               assertEquals(s1, b1.toString());
+
+       }
+
+       @Test
+       public void testHashCode() {
+               final Set<Bandwidth> set = new HashSet<Bandwidth>();
+
+               set.add(b1);
+               assertEquals(1, set.size());
+
+               set.add(b2);
+               assertEquals(2, set.size());
+
+               set.add(b3);
+               assertEquals(2, set.size());
+
+               set.add(b4);
+               assertEquals(3, set.size());
+       }
+
+       @Test
+       public void testCompareTo() {
+               final Set<Bandwidth> set = new TreeSet<Bandwidth>();
+
+               set.add(b1);
+               assertEquals(1, set.size());
+
+               set.add(b2);
+               assertEquals(2, set.size());
+
+               set.add(b3);
+               assertEquals(2, set.size());
+
+               set.add(b4);
+               assertEquals(3, set.size());
+       }
+}
+
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/IGPMetricTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/IGPMetricTest.java
new file mode 100644 (file)
index 0000000..3f71805
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+public class IGPMetricTest {
+
+       @Test
+       public void testOverflows() {
+               try {
+                       new IGPMetric(-2);
+                       fail("Constructor successful unexpectedly");
+               } catch(IllegalArgumentException e) {}
+               try {
+                       new IGPMetric(16777216);
+                       fail("Constructor successful unexpectedly");
+               } catch(IllegalArgumentException e) {}
+       }
+
+       @Test
+       public void testGetValue() {
+               IGPMetric metric = new IGPMetric(951357);
+               assertEquals(951357, metric.getValue());
+       }
+
+       @Test
+       public void testEqualsObject() {
+               IGPMetric metric1 = new IGPMetric(159357);
+               IGPMetric metric2 = new IGPMetric(159357);
+               IGPMetric metric3 = new IGPMetric(258456);
+               IGPMetric metric4 = metric3;
+
+               assertEquals(metric1, metric2);
+               assertEquals(metric1.hashCode(), metric2.hashCode());
+               assertEquals(metric3, metric4);
+               assertNotNull(metric1);
+               assertThat(metric1, not(new Object()));
+               assertThat(metric1, not(metric3));
+               assertThat(metric1.hashCode(), not(metric3.hashCode()));
+       }
+
+}
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/IPAddressesAndPrefixesTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/IPAddressesAndPrefixesTest.java
new file mode 100644 (file)
index 0000000..5c7da2e
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import static org.junit.Assert.assertTrue;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+
+public class IPAddressesAndPrefixesTest {
+
+       @Test
+       public void test1(){
+               assertTrue(IPAddresses.parseNetworkAddress("123.123.123.123") instanceof IPv4Address);
+               assertTrue(IPAddresses.parseNetworkAddress("2001::1") instanceof IPv6Address);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void test2(){
+               IPAddresses.parseNetworkAddress("256.125.126.256");
+       }
+
+       @Test
+       public void test3() {
+               assertTrue("123.123.123.123".equals(IPv4.FAMILY.addressForString("123.123.123.123").toString()));
+               assertTrue("2001:0:0:0:0:0:0:1".equals(IPv6.FAMILY.addressForString("2001::1").toString()));
+       }
+
+       @Test
+       public void test4() throws UnknownHostException{
+               assertTrue(IPAddresses.createNetworkAddress(InetAddress.getByName("123.123.123.123")) instanceof IPv4Address);
+               assertTrue(IPAddresses.createNetworkAddress(InetAddress.getByName("2001::1")) instanceof IPv6Address);
+       }
+
+       @Test
+       public void test5() {
+               assertTrue("123.123.123.0/24".equals(IPv4.FAMILY.addressForString("123.123.123.123").asPrefix(24).toString()));
+               assertTrue("123.123.123.0/24".equals(IPv4.FAMILY.prefixForString("123.123.123.123/24").toString()));
+               assertTrue("2001:0:0:0:0:0:0:0/120".equals(IPv6.FAMILY.addressForString("2001::1").asPrefix(120).toString()));
+               assertTrue("2001:0:0:0:0:0:0:0/120".equals(IPv6.FAMILY.prefixForString("2001::1/120").toString()));
+       }
+}
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/IPv4AddressTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/IPv4AddressTest.java
new file mode 100644 (file)
index 0000000..4435c00
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+
+public class IPv4AddressTest {
+       private IPv4Address a1, a2, a3, a4, a5;
+
+       @Before
+       public void setUp() {
+               this.a1 = IPv4.FAMILY.addressForString("10.0.0.1");
+               this.a2 = IPv4.FAMILY.addressForString("10.0.0.2");
+               this.a3 = IPv4.FAMILY.addressForString("10.0.0.2");
+               this.a4 = IPv4.FAMILY.addressForString("10.0.0.0");
+               this.a5 = this.a4.applyMask(24);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testFactoryFailure() {
+               final byte[] fail_bytes = { 1, 2, 3, 4, 5 };
+               new IPv4Address(fail_bytes);
+       }
+
+       @Test
+       public void testFactorySuccess() {
+               final byte[] succ_bytes = { 10, 0, 0, 1 };
+
+               final IPv4Address a = new IPv4Address(succ_bytes);
+               assertEquals(this.a1, a);
+               assertArrayEquals(a.getAddress(), succ_bytes);
+       }
+
+       @Test
+       public void testEquals() {
+               assertEquals(this.a2, this.a3);
+               assertFalse(this.a1.equals(this.a2));
+               assertFalse(this.a1.equals(new Object()));
+       }
+
+       @Test
+       public void testHashCode() {
+               final Set<IPv4Address> set = Sets.newHashSet();
+
+               set.add(this.a1);
+               assertEquals(1, set.size());
+
+               set.add(this.a2);
+               assertEquals(2, set.size());
+
+               set.add(this.a3);
+               assertEquals(2, set.size());
+
+               set.add(this.a4);
+               assertEquals(3, set.size());
+       }
+
+       @Test
+       public void testCompareTo() throws Exception {
+               final Set<IPv4Address> set = Sets.newTreeSet();
+
+               set.add(this.a1);
+               assertEquals(1, set.size());
+
+               set.add(this.a2);
+               assertEquals(2, set.size());
+
+               set.add(this.a3);
+               assertEquals(2, set.size());
+
+               set.add(this.a4);
+               assertEquals(3, set.size());
+       }
+
+       @Test
+       public void testCompareToExtended() {
+               IPv4Address an1 = IPv4.FAMILY.addressForString("192.168.4.5");
+               IPv4Address an2 = IPv4.FAMILY.addressForString("190.168.4.5");
+
+               assertEquals(2, an1.compareTo(an2));
+               assertFalse(an1.equals(an2));
+
+               assertEquals(-2, an2.compareTo(an1));
+               assertFalse(an2.equals(an1));
+
+               an1 = IPv4.FAMILY.addressForString("192.10.4.5");
+               an2 = IPv4.FAMILY.addressForString("10.10.4.5");
+
+               assertEquals(182, an1.compareTo(an2));
+               assertFalse(an1.equals(an2));
+
+               assertEquals(-182, an2.compareTo(an1));
+               assertFalse(an2.equals(an1));
+
+               an1 = IPv4.FAMILY.addressForString("255.10.4.5");
+               an2 = IPv4.FAMILY.addressForString("0.10.4.5");
+
+               assertEquals(255, an1.compareTo(an2));
+               assertFalse(an1.equals(an2));
+
+               assertEquals(-255, an2.compareTo(an1));
+               assertFalse(an2.equals(an1));
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testIllegalArgument() {
+               IPv4.FAMILY.addressForString("2001:db8:85a3:0:0:8a2e:370:7332");
+       }
+
+       @Test
+       public void testToString() {
+               assertEquals("10.0.0.1", this.a1.toString());
+               assertEquals("10.0.0.2", this.a2.toString());
+               assertEquals("10.0.0.2", this.a3.toString());
+               assertEquals("10.0.0.0", this.a4.toString());
+               assertEquals("10.0.0.0", this.a5.toString());
+       }
+}
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/IPv4PrefixTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/IPv4PrefixTest.java
new file mode 100644 (file)
index 0000000..d3d50b0
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class IPv4PrefixTest {
+       private Prefix<IPv4Address> p1, p2, p3, p4;
+       private IPv4Address addr;
+
+       @Before
+       public void setUp() throws Exception {
+               p1 = new IPv4Prefix(new IPv4Address(InetAddress.getByName("10.0.0.1")), 32);
+               p2 = new IPv4Prefix(new IPv4Address(InetAddress.getByName("10.0.0.2")), 32);
+               p3 = new IPv4Prefix(new IPv4Address(InetAddress.getByName("10.0.0.2")), 32);
+               p4 = new IPv4Prefix(new IPv4Address(InetAddress.getByName("10.0.0.0")), 24);
+               addr = new IPv4Address(InetAddress.getByName("1.2.3.4"));
+       }
+
+       @Test
+       public void testGetLength() {
+               assertEquals(32, p1.getLength());
+               assertEquals(32, p2.getLength());
+               assertEquals(32, p3.getLength());
+               assertEquals(24, p4.getLength());
+       }
+
+       @Test
+       public void testEquals() {
+               Prefix<IPv4Address> p5 = p4;
+               assertEquals(p4, p5);
+               assertNotNull(p4);
+               assertThat(p4, not(new Object()));
+               assertEquals(p2, p3);
+       }
+
+       @Test
+       public void testHashCode() {
+               final Set<Prefix<IPv4Address>> set = new HashSet<Prefix<IPv4Address>>();
+
+               set.add(p1);
+               assertEquals(1, set.size());
+
+               set.add(p2);
+               assertEquals(2, set.size());
+
+               set.add(p3);
+               assertEquals(2, set.size());
+
+               set.add(p4);
+               assertEquals(3, set.size());
+       }
+
+       @Test
+       public void testCompareTo() {
+               final Set<Prefix<IPv4Address>> set = new TreeSet<Prefix<IPv4Address>>();
+
+               set.add(p1);
+               assertEquals(1, set.size());
+
+               set.add(p2);
+               assertEquals(2, set.size());
+
+               set.add(p3);
+               assertEquals(2, set.size());
+
+               set.add(p4);
+               assertEquals(3, set.size());
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testNegativeLength() {
+               new IPv4Prefix(addr, -1);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testLongLength() {
+               new IPv4Prefix(addr, 33);
+       }
+
+       @Test
+       public void testToString() {
+               String name1 = p1.getAddress().toString() +"/"+ p1.getLength();
+               assertEquals(name1, p1.toString());
+
+               String name2 = p2.getAddress().toString() +"/"+ p2.getLength();
+               assertEquals(name2, p2.toString());
+       }
+
+       @Test
+       public void testMatches() throws Exception {
+               IPv4Address address1 = new IPv4Address(InetAddress.getByName("10.0.0.1"));
+               IPv4Address address2 = new IPv4Address(InetAddress.getByName("10.0.0.2"));
+               IPv4Prefix p1 = new IPv4Prefix(address1, 32);
+               IPv4Prefix p2 = new IPv4Prefix(address1, 16);
+               assertTrue(p1.contains(address1));
+               assertFalse(p1.contains(address2));
+               assertTrue(p2.contains(address1));
+               assertTrue(p2.contains(address2));
+       }
+
+       @Test
+       public void testApplyMask() throws Exception {
+               final IPv4Address addr = new IPv4Address(InetAddress.getByName("10.1.2.3"));
+               final IPv4Prefix p5 = new IPv4Prefix(addr, 30);
+               final IPv4Prefix p6 = new IPv4Prefix(addr, 31);
+               final IPv4Prefix p7 = new IPv4Prefix(addr, 32);
+               final IPv4Prefix p8 = new IPv4Prefix(addr, 16);
+
+               assertFalse(addr == p5.getAddress());
+               assertFalse(addr == p6.getAddress());
+               assertFalse(addr == p7.getAddress());
+               assertEquals("10.1.2.3", addr.toString());
+               assertEquals("10.1.2.0/30", p5.toString());
+               assertEquals("10.1.2.2/31", p6.toString());
+               assertEquals("10.1.2.3/32", p7.toString());
+               assertEquals("10.1.0.0/16", p8.toString());
+       }
+}
+
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/IPv6AddressTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/IPv6AddressTest.java
new file mode 100644 (file)
index 0000000..e012b6d
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class IPv6AddressTest {
+       private IPv6Address a1, a2, a3, a4, a5;
+
+       @Before
+       public void setUp() throws Exception {
+               this.a1 = new IPv6Address(
+                               InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7331"));
+               this.a2 = new IPv6Address(
+                               InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7332"));
+               this.a3 = new IPv6Address(
+                               InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7332"));
+               this.a4 = new IPv6Address(
+                               InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:0000"));
+               this.a5 = this.a4.applyMask(112);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testFailingFactory() {
+               final byte[] fail_bytes = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+                               14, 15, 16, 17 };
+
+               new IPv6Address(fail_bytes);
+       }
+
+       @Test
+       public void testFactory() {
+               final byte[] succ_bytes = { 32, 1, 13, -72, -123, -93, 0, 0, 0, 0,
+                               -118, 46, 3, 112, 115, 49 };
+
+               final IPv6Address a = new IPv6Address(succ_bytes);
+               assertEquals(this.a1, a);
+               assertEquals(succ_bytes, a.getAddress());
+       }
+
+       @Test
+       public void testEquals() {
+               assertTrue(this.a2.equals(this.a3));
+               assertFalse(this.a1.equals(this.a2));
+               assertFalse(this.a1.equals(new Object()));
+       }
+
+       @Test
+       public void testHashCode() {
+               final Set<IPv6Address> set = new HashSet<IPv6Address>();
+
+               set.add(this.a1);
+               assertEquals(1, set.size());
+
+               set.add(this.a2);
+               assertEquals(2, set.size());
+
+               set.add(this.a3);
+               assertEquals(2, set.size());
+
+               set.add(this.a4);
+               assertEquals(3, set.size());
+       }
+
+       @Test
+       public void testCompareTo() {
+               final Set<IPv6Address> set = new TreeSet<IPv6Address>();
+
+               set.add(this.a1);
+               assertEquals(1, set.size());
+
+               set.add(this.a2);
+               assertEquals(2, set.size());
+
+               set.add(this.a3);
+               assertEquals(2, set.size());
+
+               set.add(this.a4);
+               assertEquals(3, set.size());
+       }
+
+       @Test
+       public void testCompareToExtended() throws Exception {
+               IPv6Prefix an1 = new IPv6Prefix(new IPv6Address(
+                               InetAddress.getByName("8:0:0:0:0:0:0:0")), 128);
+               IPv6Prefix an2 = new IPv6Prefix(new IPv6Address(
+                               InetAddress.getByName("1:0:0:0:0:0:0:0")), 128);
+
+               assertEquals(7, an1.compareTo(an2));
+               assertThat(an1, not(an2));
+
+               assertEquals(-7, an2.compareTo(an1));
+               assertThat(an2, not(an1));
+
+               an1 = new IPv6Prefix(new IPv6Address(
+                               InetAddress.getByName("aa:0:0:0:0:0:0:0")), 128);
+               an2 = new IPv6Prefix(new IPv6Address(
+                               InetAddress.getByName("1:0:0:0:0:0:0:0")), 128);
+
+               assertEquals(169, an1.compareTo(an2));
+               assertThat(an1, not(an2));
+
+               assertEquals(-169, an2.compareTo(an1));
+               assertThat(an2, not(an1));
+
+               an1 = new IPv6Prefix(new IPv6Address(
+                               InetAddress.getByName("ff:0:0:0:0:0:0:0")), 128);
+               an2 = new IPv6Prefix(new IPv6Address(
+                               InetAddress.getByName("0:0:0:0:0:0:0:0")), 128);
+
+               assertEquals(255, an1.compareTo(an2));
+               assertThat(an1, not(an2));
+
+               assertEquals(-255, an2.compareTo(an1));
+               assertThat(an2, not(an1));
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testIllegalArgument() throws Exception {
+               new IPv6Address(InetAddress.getByName("120.20.20.20"));
+       }
+
+       @Test
+       public void testToString() {
+               assertEquals("2001:db8:85a3:0:0:8a2e:370:7331", this.a1.toString());
+               assertEquals("2001:db8:85a3:0:0:8a2e:370:7332", this.a2.toString());
+               assertEquals("2001:db8:85a3:0:0:8a2e:370:7332", this.a3.toString());
+               assertEquals("2001:db8:85a3:0:0:8a2e:370:0", this.a4.toString());
+               assertEquals("2001:db8:85a3:0:0:8a2e:370:0", this.a5.toString());
+       }
+}
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/IPv6PrefixTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/IPv6PrefixTest.java
new file mode 100644 (file)
index 0000000..d1fa748
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.concepts;
+
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class IPv6PrefixTest {
+       private Prefix<IPv6Address> p1, p2, p3, p4;
+       private IPv6Address addr;
+
+       @Before
+       public void setUp() throws Exception {
+               p1 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7331")), 128);
+               p2 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7332")), 128);
+               p3 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7332")), 128);
+               p4 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7300")), 120);
+               addr = new IPv6Address(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7331"));
+       }
+
+       @Test
+       public void testEquals() {
+               assertTrue(p2.equals(p3));
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testNegativeLength() {
+               new IPv6Prefix(addr, -1);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testLongLength() throws Exception {
+               new IPv6Prefix(addr, 129);
+       }
+
+       @Test
+       public void testHashCode() {
+               final Set<Prefix<IPv6Address>> set = new HashSet<Prefix<IPv6Address>>();
+
+               set.add(p1);
+               assertEquals(1, set.size());
+
+               set.add(p2);
+               assertEquals(2, set.size());
+
+               set.add(p3);
+               assertEquals(2, set.size());
+
+               set.add(p4);
+               assertEquals(3, set.size());
+       }
+
+       @Test
+       public void testCompareTo() {
+               final Set<Prefix<IPv6Address>> set = new TreeSet<Prefix<IPv6Address>>();
+
+               set.add(p1);
+               assertEquals(1, set.size());
+
+               set.add(p2);
+               assertEquals(2, set.size());
+
+               set.add(p3);
+               assertEquals(2, set.size());
+
+               set.add(p4);
+               assertEquals(3, set.size());
+       }
+}
+
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/ISOSystemIdentifierTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/ISOSystemIdentifierTest.java
new file mode 100644 (file)
index 0000000..20a87fa
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ISOSystemIdentifierTest {
+
+       @Test(expected=IllegalArgumentException.class)
+       public void testISOSystemIdentifier() {
+               byte[] b = new byte[]{10,12,127,0,9,1,1};
+               new ISOSystemIdentifier(b);
+       }
+
+       @Test
+       public void testGetBytes() {
+               byte[] b = new byte[]{10,12,127,0,9,1};
+               ISOSystemIdentifier id = new ISOSystemIdentifier(b);
+               Assert.assertArrayEquals(new byte[]{10,12,127,0,9,1}, id.getBytes());
+       }
+
+}
diff --git a/concepts/src/test/java/org/opendaylight/protocol/concepts/TEMetricTest.java b/concepts/src/test/java/org/opendaylight/protocol/concepts/TEMetricTest.java
new file mode 100644 (file)
index 0000000..db7f120
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.concepts;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+public class TEMetricTest {
+
+       @Test
+       public void testOverflows() {
+               try {
+                       new TEMetric(-2);
+                       fail("Constructor successful unexpectedly");
+               } catch(IllegalArgumentException e) {}
+               try {
+                       new TEMetric(4294967296L);
+                       fail("Constructor successful unexpectedly");
+               } catch(IllegalArgumentException e) {}
+       }
+
+       @Test
+       public void testGetValue() {
+               TEMetric metric = new TEMetric(951357);
+               assertEquals(951357, metric.getValue());
+       }
+
+       @Test
+       public void testEqualsObject() {
+               TEMetric metric1 = new TEMetric(159357);
+               TEMetric metric2 = new TEMetric(159357);
+               TEMetric metric3 = new TEMetric(258456);
+               TEMetric metric4 = metric3;
+
+               assertEquals(metric1, metric2);
+               assertEquals(metric1.hashCode(), metric2.hashCode());
+               assertEquals(metric3, metric4);
+               assertNotNull(metric1);
+               assertThat(metric1, not(equalTo(new Object())));
+               assertThat(metric1, not(equalTo(metric3)));
+               assertThat(metric1.hashCode(), not(equalTo(metric3.hashCode())));
+       }
+}
+
diff --git a/framework/.gitignore b/framework/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/framework/.project b/framework/.project
new file mode 100644 (file)
index 0000000..c01307d
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>common-protocol</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/framework/pom.xml b/framework/pom.xml
new file mode 100644 (file)
index 0000000..31f45e0
--- /dev/null
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>protocol-parent</artifactId>
+               <version>0.1</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>framework</artifactId>
+       <description>Common protocol framework</description>
+       <packaging>bundle</packaging>
+       <version>1.0</version>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>com.google.guava</groupId>
+                       <artifactId>guava</artifactId>
+                       <version>${guava.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-api</artifactId>
+                       <version>${slf4j.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.opendaylight.protocol</groupId>
+                       <artifactId>util</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.opendaylight.protocol</groupId>
+                       <artifactId>mockito-configuration</artifactId>
+                       <version>1.0</version>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Import-Package>
+                                                       com.google.common.base,
+                                                       com.google.common.collect,
+                                                       org.opendaylight.protocol.concepts,
+                                                       org.slf4j,
+                            javax.net.ssl,
+                            org.opendaylight.protocol.util,
+                                                       javax.annotation,
+                                                       javax.management,
+                                               </Import-Package>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.framework,
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>${checkstyle.version}</version>
+                               <configuration>
+                                       <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+                                       <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-jar-plugin</artifactId>
+                               <version>2.4</version>
+                               <executions>
+                                       <execution>
+                                               <phase>package</phase>
+                                               <goals>
+                                                       <goal>test-jar</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>COMMON-PROTOCOL Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/DeserializerException.java b/framework/src/main/java/org/opendaylight/protocol/framework/DeserializerException.java
new file mode 100644 (file)
index 0000000..462689d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+/**
+ * Used when something occurs during parsing bytes to java objects.
+ */
+public class DeserializerException extends Exception {
+
+       private static final long serialVersionUID = -2247000673438452870L;
+
+       /**
+        * Creates a deserializer exception.
+        * @param err string
+        */
+       public DeserializerException(final String err) {
+               this(err, null);
+       }
+
+       /**
+        * Creates a deserializer exception.
+        * @param err string
+        * @param e underlying exception
+        */
+       public DeserializerException(final String err, final Exception e) {
+               super(err, e);
+       }
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/Dispatcher.java b/framework/src/main/java/org/opendaylight/protocol/framework/Dispatcher.java
new file mode 100644 (file)
index 0000000..45ac096
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import javax.net.ssl.SSLContext;
+
+/**
+ * Dispatcher class for creating protocol servers and clients. The idea is to first create servers and clients and the run the start method
+ * that will handle sockets in different thread.
+ */
+public interface Dispatcher {
+       /**
+        * Creates server. Each server needs factories to pass their instances to client sessions.
+        * @param address to be bound with the server
+        * @param connectionFactory factory for connection specific attributes
+        * @param sfactory to create specific session
+        * @param isFactory protocol specific input stream factory
+        *
+        * @return instance of ProtocolServer
+        * @throws IOException if some IO error occurred
+        */
+       public ProtocolServer createServer(final InetSocketAddress address, final ProtocolConnectionFactory connectionFactory,
+                       final ProtocolSessionFactory sfactory, final ProtocolInputStreamFactory isFactory) throws IOException;
+
+       /**
+        * Creates secure server. Each server needs factories to pass their instances to client sessions.
+        * @param address to be bound with the server
+        * @param connectionFactory factory for connection specific attributes
+        * @param sfactory to create specific session
+        * @param isFactory protocol-specific input stream factory
+        * @param context SSLContext to use in secure communications
+        *
+        * @return instance of ProtocolServer
+        * @throws IOException if some IO error occurred
+        */
+       public ProtocolServer createServer(final InetSocketAddress address, final ProtocolConnectionFactory connectionFactory,
+                       final ProtocolSessionFactory sfactory, final ProtocolInputStreamFactory isFactory, final SSLContext context) throws IOException;
+
+       /**
+        * Creates a client.
+        * @param connection connection specific attributes
+        * @param sfactory protocol message factory to be passed to session
+        * @param isFactory protocol-specific input stream factory
+        *
+        * @return session associated with this client
+        * @throws IOException if some IO error occurred
+        */
+       public ProtocolSession createClient(final ProtocolConnection connection, final ProtocolSessionFactory sfactory,
+                       final ProtocolInputStreamFactory isFactory) throws IOException;
+
+       /**
+        * Creates secure client.
+        * @param connection connection specific attributes
+        * @param sfactory protocol message factory to be passed to session
+        * @param isFactory protocol-specific input stream factory
+        * @param context SSLContext to use in secure communications
+        *
+        * @return session associated with this client
+        * @throws IOException if some IO error occurred
+        */
+       public ProtocolSession createClient(final ProtocolConnection connection, final ProtocolSessionFactory sfactory,
+                       final ProtocolInputStreamFactory isFactory, final SSLContext context) throws IOException;
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/DispatcherImpl.java b/framework/src/main/java/org/opendaylight/protocol/framework/DispatcherImpl.java
new file mode 100644 (file)
index 0000000..ed5168d
--- /dev/null
@@ -0,0 +1,769 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Queue;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+import javax.net.ssl.SSLContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+
+/**
+ * Dispatcher class for creating servers and clients. The idea is to first create servers and clients and the run the
+ * start method that will handle sockets in different thread.
+ */
+public final class DispatcherImpl implements Dispatcher, SessionParent {
+
+       private static final Logger logger = LoggerFactory.getLogger(Dispatcher.class);
+
+       public static final int DEFAULT_MAX_RECONNECT_COUNT = 30;
+
+       public static final int DEFAULT_RECONNECT_MILLIS = 30000;
+       public static final int DEFAULT_SERVICE_MILLIS = 1000;
+
+       private static final int BUFFER_SIZE = 16384;
+
+       private static final boolean SSL_ENABLED = true;
+
+       private int serviceMillis = DEFAULT_SERVICE_MILLIS;
+       private int reconnectMillis = 5000;
+
+       private int maxConnectCount = 0;
+
+       /**
+        * List of servers created by this dispatcher. Servers are identified as a pair Server and the InetSocketAddress to
+        * which the server is bound.
+        */
+       private final Map<InetSocketAddress, ProtocolServer> servers = new HashMap<InetSocketAddress, ProtocolServer>();
+
+       /**
+        * Mapping of client Sessions to keys (Either clients created by the dispatcher directly or clients connected to one
+        * of the dispatchers server).
+        */
+       private final Map<ProtocolSession, SelectionKey> sessionKeys = new HashMap<ProtocolSession, SelectionKey>();
+
+       /**
+        * List of clients created by this dispatcher. Each client has its own Session. They are identified as a pair of
+        * Session and the InetSocketAddress to which they are connected.
+        */
+       private final BiMap<InetSocketAddress, ProtocolSession> clients;
+
+       /**
+        * Timer object grouping FSM Timers
+        */
+       private final Timer stateTimer;
+
+       /**
+        * Variable indicating that there was a request for stopping this dispatcher.
+        */
+       private volatile boolean requestStop = false;
+
+       private final Thread innerThread;
+
+       private final ExecutorService executorService;
+
+       private final InnerRun innerRun;
+
+       /**
+        * Configuration dependency used for testing of reusability.
+        */
+       private final ThreadFactory threadFactory;
+
+       private final class InnerRun implements Runnable {
+
+               /**
+                * Common selector for client/server parts.
+                */
+               public final Selector selector;
+
+               private final DispatcherImpl parent;
+
+               protected InnerRun(final DispatcherImpl parent) throws IOException {
+                       final Selector s = SelectorProvider.provider().openSelector();
+
+                       if (SSL_ENABLED)
+                               this.selector = new SSLSelector(s);
+                       else
+                               this.selector = s;
+
+                       this.parent = parent;
+               }
+
+               @Override
+               public void run() {
+                       // this method finishes only when stop() method was called
+                       while (!this.parent.requestStop) {
+                               try {
+                                       this.selector.select();
+                               } catch (final IOException e) {
+                                       logger.warn("Selection operation failed", e);
+                                       break;
+                               }
+
+                               /*
+                                * This block runs under lock. The idea is that
+                                * selection key notifiers will first acquire the
+                                * lock, then wake up the selector, then do their
+                                * modifications.
+                                *
+                                * This means that there are two possibilities:
+                                *
+                                * 1) we arrive here as a result of a selector wake
+                                *    up, at which point the modifier already holds
+                                *    the lock, and we'll wait for it.
+                                *
+                                * 2) we arrive here as a result of an event, in which
+                                *    case we will prevent modifiers from starting
+                                *    by holding the lock.
+                                */
+                               // logger.debug("Acquiring lock");
+                               synchronized (this) {
+                                       final Set<SelectionKey> keys = this.selector.selectedKeys();
+                                       if (keys.isEmpty())
+                                               continue;
+
+                                       /*
+                                        * Calculate maximum nanoseconds we can spend on read
+                                        * or write. Each key can do a pair of operations in one
+                                        * iteration.
+                                        */
+                                       final long serviceTime = serviceMillis * 500000 / keys.size();
+
+                                       final Iterator<SelectionKey> selectedKeys = keys.iterator();
+                                       while (selectedKeys.hasNext()) {
+                                               final SelectionKey key = selectedKeys.next();
+                                               selectedKeys.remove();
+
+                                               if (!key.isValid()) {
+                                                       continue;
+                                               }
+
+                                               try {
+                                                       if (key.isAcceptable()) {
+                                                               this.parent.accept(key);
+                                                       }
+                                                       if (key.isConnectable()) {
+                                                               if (!this.parent.finishConnection(key)) {
+                                                                       continue;
+                                                               }
+                                                       }
+
+                                                       /*
+                                                        * Split read/write fairness. If this key is only
+                                                        * readable or only writable, double the time
+                                                        */
+                                                       final long keyTime = key.isReadable() == key.isWritable() ? serviceTime : 2 * serviceTime;
+
+                                                       /*
+                                                        * If this key is readable, read it. That operation may
+                                                        * detect end-of-stream, which it will report internally,
+                                                        * and inform us by returning true.
+                                                        *
+                                                        * If that is the case, we do not want to proceed with the
+                                                        * write case, because the key may no longer be valid.
+                                                        */
+                                                       if (key.isReadable() && this.parent.read(key, System.nanoTime() + keyTime)) {
+                                                               continue;
+                                                       }
+
+                                                       /*
+                                                        * If this key is writable, write it. This may completely
+                                                        * drain the output queue, in which case write returns true.
+                                                        *
+                                                        * If that is the case, we need to suspend selecting for
+                                                        * writability -- it will be re-enabled once the queue goes
+                                                        * non-empty.
+                                                        */
+                                                       if (key.isWritable() && this.parent.write(key, System.nanoTime() + keyTime) && key.isValid()) {
+                                                               key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
+                                                       }
+
+                                               } catch (final IOException e) {
+                                                       logger.debug("Channel {} incurred unexpected error, closing it", key.channel(), e);
+                                                       key.cancel();
+                                                       try {
+                                                               key.channel().close(); // close the channel that caused problems
+                                                       } catch (final IOException e1) {
+                                                               logger.error("Channel: {} could not be closed, because {}", key.channel(), e1.getMessage(), e1);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       logger.trace("Ended run of dispatcher.");
+                       try {
+                               this.selector.close();
+                       } catch (final IOException e) {
+                               throw new RuntimeException("Failed to close selector", e);
+                       }
+               }
+       }
+
+       /**
+        * Creates an instance of Dispatcher, gets the default selector and opens it.
+        *
+        * @param tfactory default Thread Factory
+        * @throws IOException if some error occurred during opening the selector
+        */
+       public DispatcherImpl(final ThreadFactory tfactory) throws IOException {
+               this.threadFactory = tfactory;
+               this.executorService = Executors.newSingleThreadExecutor(tfactory);
+               this.stateTimer = new Timer();
+               this.clients = HashBiMap.create();
+               this.innerRun = new InnerRun(this);
+               this.innerThread = tfactory.newThread(this.innerRun);
+               this.innerThread.start();
+       }
+
+       protected synchronized ProtocolServer startServer(final ServerSocketChannel serverChannel, final InetSocketAddress address,
+                       final ProtocolConnectionFactory connectionFactory, final ProtocolSessionFactory sfactory,
+                       final ProtocolInputStreamFactory isFactory) throws IOException {
+
+               // Notify the thread to update its selection keys
+               this.innerRun.selector.wakeup();
+
+               // logger.debug("Selector notified.");
+               serverChannel.configureBlocking(false);
+               serverChannel.bind(address);
+
+               final SelectionKey key = serverChannel.register(this.innerRun.selector, SelectionKey.OP_ACCEPT);
+               final ProtocolServer server = new ProtocolServer(this, address, serverChannel, connectionFactory, sfactory, isFactory);
+               key.attach(server);
+               this.servers.put(address, server);
+
+               logger.info("Server created.");
+               return server;
+       }
+
+       @Override
+       public ProtocolServer createServer(final InetSocketAddress address, final ProtocolConnectionFactory connectionFactory,
+                       final ProtocolSessionFactory sfactory, final ProtocolInputStreamFactory isFactory) throws IOException {
+               synchronized (this.innerRun) {
+                       if (this.servers.get(address) != null) {
+                               logger.warn("Server with this address: {} was already created.", address);
+                               throw new IllegalStateException("Server with this address: " + address + " was already created.");
+                       }
+
+                       return this.startServer(ServerSocketChannel.open(), address, connectionFactory, sfactory, isFactory);
+               }
+       }
+
+       @Override
+       public ProtocolServer createServer(final InetSocketAddress address, final ProtocolConnectionFactory connectionFactory,
+                       final ProtocolSessionFactory sfactory, final ProtocolInputStreamFactory isFactory, final SSLContext context) throws IOException {
+
+               if (!SSL_ENABLED)
+                       throw new UnsupportedOperationException("SSL has not been enabled");
+
+               synchronized (this.innerRun) {
+                       if (this.servers.get(address) != null) {
+                               logger.warn("Server with this address: {} was already created.", address);
+                               throw new IllegalStateException("Server with this address: " + address + " was already created.");
+                       }
+
+                       return this.startServer(SSLServerSocketChannel.open(this.innerRun.selector, context, this.executorService), address,
+                                       connectionFactory, sfactory, isFactory);
+               }
+       }
+
+       private void connectChannel(final SelectionKey key) {
+               final SessionStreams state = (SessionStreams) key.attachment();
+               state.timer = null;
+
+               state.connectCount++;
+               logger.debug("Connecting to {} attempt {}", state.connection.getPeerAddress(), state.connectCount);
+
+               final SocketChannel channel = (SocketChannel) key.channel();
+               try {
+                       channel.connect(state.connection.getPeerAddress());
+               } catch (final IOException e) {
+                       this.connectFailed(key, e);
+                       return;
+               }
+
+               if (channel.isConnected()) {
+                       logger.trace("Connected, update interestops");
+                       key.interestOps(SelectionKey.OP_READ);
+                       state.getSession().startSession();
+               } else
+                       key.interestOps(SelectionKey.OP_CONNECT);
+       }
+
+       private void connectFailed(final SelectionKey key, final IOException e) {
+               final SessionStreams state = (SessionStreams) key.attachment();
+
+               key.interestOps(0);
+
+               if (this.maxConnectCount >= 0 && state.connectCount >= this.maxConnectCount) {
+                       logger.debug("Connection to {} failed", state.connection.getPeerAddress().getAddress(), e);
+                       this.clients.inverse().remove(state.getSession());
+                       state.getSession().onConnectionFailed(e);
+                       return;
+               }
+
+               logger.trace("Connect to {} failed, will retry in {} milliseconds", state.connection.getPeerAddress().getAddress(),
+                               this.reconnectMillis, e);
+               state.timer = new TimerTask() {
+                       @Override
+                       public void run() {
+                               DispatcherImpl.this.connectChannel(key);
+                       }
+               };
+               this.stateTimer.schedule(state.timer, this.reconnectMillis);
+       }
+
+       private ProtocolSession startClient(final SocketChannel channel, final ProtocolConnection connection,
+                       final ProtocolSessionFactory sfactory, final ProtocolInputStreamFactory isFactory) throws IOException {
+
+               // Notify the thread to update its selection keys
+               this.innerRun.selector.wakeup();
+
+               channel.configureBlocking(false);
+
+               final ProtocolSession session;
+               final SelectionKey key;
+               synchronized (this) {
+                       session = sfactory.getProtocolSession(this, this.stateTimer, connection, 0);
+
+                       final PipedOutputStream pos = new PipedOutputStream();
+                       final PipedInputStream pis = new PipedInputStream(pos, session.maximumMessageSize());
+
+                       key = channel.register(this.innerRun.selector, SelectionKey.OP_CONNECT);
+                       key.attach(new SessionStreams(pos, pis, isFactory.getProtocolInputStream(pis, session.getMessageFactory()), session, connection));
+
+                       this.sessionKeys.put(session, key);
+                       this.clients.put(connection.getPeerAddress(), session);
+                       logger.info("Client created.");
+               }
+
+               this.connectChannel(key);
+               return session;
+       }
+
+       @Override
+       public ProtocolSession createClient(final ProtocolConnection connection, final ProtocolSessionFactory sfactory,
+                       final ProtocolInputStreamFactory isFactory) throws IOException {
+               synchronized (this.innerRun) {
+                       if (this.clients.containsKey(connection.getPeerAddress())) {
+                               logger.warn("Attempt to create duplicate client session to the same address: {}", connection.getPeerAddress());
+                               throw new IllegalStateException("Attempt to create duplicate client session to the same address: "
+                                               + connection.getPeerAddress());
+                       }
+
+                       return this.startClient(SocketChannel.open(), connection, sfactory, isFactory);
+               }
+       }
+
+       @Override
+       public ProtocolSession createClient(final ProtocolConnection connection, final ProtocolSessionFactory sfactory,
+                       final ProtocolInputStreamFactory isFactory, final SSLContext context) throws IOException {
+
+               if (!SSL_ENABLED)
+                       throw new UnsupportedOperationException("SSL has not been enabled");
+
+               synchronized (this.innerRun) {
+                       if (this.clients.containsKey(connection.getPeerAddress())) {
+                               logger.warn("Attempt to create duplicate client session to the same address: {}", connection.getPeerAddress());
+                               throw new IllegalStateException("Attempt to create duplicate client session to the same address: "
+                                               + connection.getPeerAddress());
+                       }
+
+                       final SocketChannel sock = SSLSocketChannel.open(SocketChannel.open(), context, this.executorService, null);
+                       return this.startClient(sock, connection, sfactory, isFactory);
+               }
+       }
+
+       /**
+        * Requests to stop dispatchers run() method. This method wakes up the selector, even if there are no selectedKeys
+        * to stop blocking the thread.
+        */
+       public void stop() {
+               logger.debug("Requested stop of the Dispatcher.");
+               this.requestStop = true;
+               this.innerRun.selector.wakeup();
+               try {
+                       this.innerThread.join();
+               } catch (final InterruptedException e) {
+                       logger.error("Stopping interrupted.", e);
+               }
+
+               this.executorService.shutdown();
+       }
+
+       /**
+        * Removes given server from list of servers created by this dispatcher.
+        *
+        * @param server to be removed
+        */
+       void removeServer(final ProtocolServer server) {
+               this.servers.remove(server.getAddress());
+               logger.trace("Server removed.");
+       }
+
+       /**
+        * Reads from socket and sends data to session through Piped Streams.
+        *
+        * @param key selection key that was marked as ready to read from
+        * @return true if the read has encountered end of channel (so no data will ever come) false if the method did read
+        *         all of its input
+        * @throws IOException if there was some error with IO streams
+        */
+       private boolean read(final SelectionKey key, final long deadline) throws IOException {
+               logger.trace("Started reading.");
+               final SocketChannel chan = (SocketChannel) key.channel();
+               final SessionStreams streams = (SessionStreams) key.attachment();
+               final ProtocolInputStream pcepis = streams.getProtocolInputStream();
+               final PipedOutputStream pos = streams.getPipedOutputStream();
+               final PipedInputStream pis = streams.getPipedInputStream();
+               final ProtocolSession session = streams.getSession();
+
+               try {
+                       final ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
+                       int r = chan.read(byteBuffer);
+
+                       while (r != 0) {
+                               byteBuffer.flip();
+
+                               // if we have some unread data in the buffer
+                               while (byteBuffer.hasRemaining()) {
+                                       final int pisFree = session.maximumMessageSize() - pis.available();
+                                       if (pisFree == 0)
+                                               throw new IOException("Protocol failed to detect no-progress situation");
+
+                                       int toMove = byteBuffer.remaining();
+
+                                       // Do not try to write more than the input stream can accept
+                                       if (toMove > pisFree)
+                                               toMove = pisFree;
+
+                                       // Write to the output stream and adjust buffer position
+                                       pos.write(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(), toMove);
+                                       byteBuffer.position(byteBuffer.position() + toMove);
+
+                                       // Notify input stream that it can read more stuff
+                                       pos.flush();
+
+                                       // process any messages which became available
+                                       while (pcepis.isMessageAvailable()) {
+                                               // read and parse message
+                                               final ProtocolMessage msg = pcepis.getMessage();
+                                               // send it to session for handling
+                                               session.handleMessage(msg);
+                                       }
+                               }
+                               byteBuffer.clear();
+
+                               /*
+                                * We reached end-of-input stream. Notify close the output stream
+                                * and notify the user. He is then supposed to close the session,
+                                * releasing the write-end of things.
+                                */
+                               if (r == -1) {
+                                       logger.warn("End of input stream reached.");
+                                       /*
+                                        * The input stream has some bytes, but no others are coming
+                                        * in. This means it should have been a complete message,
+                                        * but is not -> that's a malformed message.
+                                        */
+                                       if (pis.available() != 0) {
+                                               logger.warn("Received incomplete message.");
+                                               throw new DeserializerException("Incomplete message at the end of input stream");
+                                       }
+                                       key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
+                                       session.endOfInput();
+                                       return true;
+                               }
+
+                               if (!chan.isOpen())
+                                       return true;
+
+                               final long now = System.nanoTime();
+                               if (deadline <= now) {
+                                       logger.trace("Read service time exceeded by {} nanoseconds.", now - deadline);
+                                       break;
+                               }
+
+                               r = chan.read(byteBuffer);
+                       }
+               } catch (final DeserializerException e) {
+                       // An unrecoverable malformed message has been received. Notify
+                       // session to take care of the fallout.
+                       logger.warn("Malformed message {}", e.getMessage(), e);
+                       session.handleMalformedMessage(e);
+               } catch (final DocumentedException e) {
+                       // A potentially recoverable malformed message has been received.
+                       // Push it to the session, it will take care of the details.
+                       logger.warn("Malformed message {}", e.getMessage(), e);
+                       session.handleMalformedMessage(e);
+               } catch (final RuntimeException e) {
+                       logger.error("Unrecoverable internal session error: {}", e.getMessage(), e);
+                       throw new IOException("Unrecoverable internal session error", e);
+               }
+               return false;
+       }
+
+       /**
+        * Writes data from ProtocolOutputStream to socket.
+        *
+        * @param key selection key that was marked as ready to write from
+        * @return false if the writing was not successful true if the queue of messages became empty
+        * @throws IOException if there was some error with the IO streams
+        */
+       private boolean write(final SelectionKey key, final long deadline) throws IOException {
+               logger.trace("Started writing.");
+
+               // TODO: promote to hard error?
+               final SocketChannel socketChannel = (SocketChannel) key.channel();
+               if (!socketChannel.isConnected()) {
+                       logger.warn("Channel is not connected yet.");
+                       return false;
+               }
+
+               final SessionStreams streams = (SessionStreams) key.attachment();
+               final Queue<ByteBuffer> queue = streams.getSession().getStream().getBuffers();
+
+               synchronized (queue) {
+                       logger.trace("Synchronized writing started.");
+                       // Write until there's not more data
+                       while (!queue.isEmpty()) {
+                               final ByteBuffer buf = queue.element();
+                               socketChannel.write(buf);
+                               if (buf.remaining() > 0) {
+                                       /*
+                                        * If there is not enough space in the socket to write all the data
+                                        * stay in writing mode and attempt to write after the next select()
+                                        * call
+                                        */
+                                       logger.trace("Socket queue full.");
+                                       return false;
+                               }
+                               queue.remove();
+
+                               final long now = System.nanoTime();
+                               if (deadline <= now) {
+                                       logger.trace("Write service time exceeded by {} nanoseconds.", now - deadline);
+                                       return false;
+                               }
+                       }
+                       logger.trace("Write queue empty.");
+                       return true;
+               }
+       }
+
+       private void acceptChannel(final ProtocolServer server, final SocketChannel socketChannel, final InetSocketAddress clientAddress)
+                       throws IOException {
+               socketChannel.configureBlocking(false);
+
+               final ProtocolSession s = server.createSession(this.stateTimer, clientAddress);
+               final PipedOutputStream pos = new PipedOutputStream();
+               final PipedInputStream pis = new PipedInputStream(pos, s.maximumMessageSize());
+               final ProtocolInputStream inputStream = server.createInputStream(pis, s.getMessageFactory());
+
+               final SelectionKey skey = socketChannel.register(this.innerRun.selector, SelectionKey.OP_READ);
+               skey.attach(new SessionStreams(pos, pis, inputStream, s, null));
+               this.sessionKeys.put(s, skey);
+
+               // FIXME: catch RuntimeExceptions here, undo the put/attach above?
+               // or can we move the .put() after this call?
+               s.startSession();
+       }
+
+       /**
+        * Accepts incoming connection from a client to one of the running servers.
+        *
+        * @param key selection key that was marked as ready to accept connections
+        * @throws IOException if there was some error with IO streams
+        */
+       private void accept(final SelectionKey key) throws IOException {
+               final ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
+               final SocketChannel socketChannel = serverSocketChannel.accept();
+               if (socketChannel == null)
+                       return;
+
+               final InetSocketAddress clientAddress = (InetSocketAddress) socketChannel.getRemoteAddress();
+               logger.info("Requested connection for: {}", clientAddress.getAddress().getHostAddress());
+
+               try {
+                       this.acceptChannel((ProtocolServer) key.attachment(), socketChannel, clientAddress);
+               } catch (final Exception e) {
+                       logger.warn("Failed to start protocol session", e);
+                       socketChannel.close();
+               }
+       }
+
+       /**
+        * Finishes connection of the client to the server. Starts session.
+        *
+        * @param key selection key that was marked as ready to finish connection
+        */
+       private boolean finishConnection(final SelectionKey key) {
+               final SocketChannel socketChannel = (SocketChannel) key.channel();
+               final SessionStreams streams = (SessionStreams) key.attachment();
+               logger.trace("Finishing connection for key {}", key);
+               try {
+                       if (socketChannel.finishConnect()) {
+                               key.interestOps(SelectionKey.OP_READ);
+                               streams.getSession().startSession();
+                       }
+               } catch (final IOException e) {
+                       this.connectFailed(key, e);
+                       return false;
+               }
+               return true;
+       }
+
+       /**
+        * Closes channel and cancels key assigned to given session.
+        *
+        * @param session session that was closed
+        */
+       void closeSessionSockets(final ProtocolSession session) {
+               synchronized (this.innerRun) {
+                       logger.debug("Trying to close sesion.");
+                       final SelectionKey key = this.sessionKeys.get(session);
+                       if (key != null) {
+
+                               try {
+                                       key.channel().close();
+                               } catch (final IOException e) {
+                                       logger.error("Session channel could not be closed.");
+                               } finally {
+                                       final SessionStreams streams = (SessionStreams) key.attachment();
+                                       if (streams.timer != null) {
+                                               streams.timer.cancel();
+                                               streams.timer = null;
+                                       }
+
+                                       logger.trace("Cancelling key.");
+                                       key.cancel();
+
+                                       final PipedOutputStream pos = streams.getPipedOutputStream();
+                                       try {
+                                               pos.close();
+                                       } catch (final IOException e) {
+                                               logger.error("Session-internal output stream could not be closed.");
+                                       } finally {
+                                               final PipedInputStream pis = streams.getPipedInputStream();
+                                               try {
+                                                       pis.close();
+                                               } catch (final IOException e) {
+                                                       logger.error("Session-internal input stream could not be closed.");
+                                               }
+                                       }
+                               }
+                       }
+                       this.sessionKeys.remove(key);
+                       logger.debug("Session sockets closed.");
+               }
+       }
+
+       @Override
+       public void onSessionClosed(final ProtocolSession session) {
+               synchronized (this.innerRun) {
+                       this.innerRun.selector.wakeup();
+                       this.closeSessionSockets(session);
+                       this.clients.inverse().remove(session);
+                       logger.debug("Session {} removed.", session);
+               }
+       }
+
+       @Override
+       public void checkOutputBuffer(final ProtocolSession session) {
+               final SelectionKey key = this.sessionKeys.get(session);
+               key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
+               key.selector().wakeup();
+       }
+
+       @Override
+       public void close() throws IOException {
+               for (final Entry<InetSocketAddress, ProtocolServer> s : this.servers.entrySet()) {
+                       s.getValue().close();
+               }
+               for (final Entry<InetSocketAddress, ProtocolSession> s : this.clients.entrySet()) {
+                       s.getValue().close();
+               }
+       }
+
+       /**
+        * Gets milliseconds between reconnects.
+        * @return time in milliseconds between reconnects
+        */
+       public synchronized int getReconnectMillis() {
+               return this.reconnectMillis;
+       }
+
+       /**
+        * Sets milliseconds between reconnects.
+        * @param reconnectMillis new value
+        */
+       public synchronized void setReconnectMillis(final int reconnectMillis) {
+               Preconditions.checkArgument(reconnectMillis > 0, "Reconnect milliseconds value has to be positive");
+               this.reconnectMillis = reconnectMillis;
+               // FIXME: readjust all pending timers
+       }
+
+       /**
+        * Gets maximum tries for connection.
+        * @return max connection count
+        */
+       public synchronized int getMaxConnectCount() {
+               return this.maxConnectCount;
+       }
+
+       /**
+        * Sets maximum tries for connection.
+        * @param maxConnectCount new value
+        */
+       public synchronized void setMaxConnectCount(final int maxConnectCount) {
+               this.maxConnectCount = maxConnectCount;
+               // FIXME: purge all sessions which already exceed the limit
+       }
+
+       public synchronized int getServiceMillis() {
+               return this.serviceMillis;
+       }
+
+       public synchronized void setServiceMillis(final int serviceMillis) {
+               Preconditions.checkArgument(serviceMillis > 0);
+               this.serviceMillis = serviceMillis;
+       }
+
+       /**
+        * Gets thread factory.
+        * @return thread factory
+        */
+       public ThreadFactory getThreadFactory() {
+               return this.threadFactory;
+       }
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/DocumentedException.java b/framework/src/main/java/org/opendaylight/protocol/framework/DocumentedException.java
new file mode 100644 (file)
index 0000000..640fefa
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+/**
+ * Documented exception occurrs when an error is thrown that is documented
+ * in any RFC or draft for the specific protocol.
+ */
+public class DocumentedException extends Exception  {
+
+       private static final long serialVersionUID = -3727963789710833704L;
+
+       /**
+        * Creates a documented exception
+        * @param message string
+        */
+       public DocumentedException(final String message) {
+               this(message, null);
+       }
+
+       /**
+        * Creates a documented exception
+        * @param err string
+        * @param e underlying exception
+        */
+       public DocumentedException(final String err, final Exception e) {
+               super(err, e);
+       }
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolConnection.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolConnection.java
new file mode 100644 (file)
index 0000000..f867926
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.net.InetSocketAddress;
+
+/**
+ * Specifies connection attributes.
+ */
+public interface ProtocolConnection {
+
+       /**
+        * Returns address to which the connection should bind.
+        * @return inet socket address
+        */
+       InetSocketAddress getPeerAddress();
+
+       /**
+        * Returns listener for the session.
+        * @return listener for the session
+        */
+       SessionListener getListener();
+
+       /**
+        * Returns session preferences (attributes for Open object).
+        * @return session preferences
+        */
+       SessionPreferences getProposal();
+
+       /**
+        * Returns session preferences checker.
+        * @return session preferences checker
+        */
+       SessionPreferencesChecker getProposalChecker();
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolConnectionFactory.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolConnectionFactory.java
new file mode 100644 (file)
index 0000000..4e1d1d1
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.net.InetSocketAddress;
+
+/**
+ * Factory creating Protocol connections.
+ */
+public interface ProtocolConnectionFactory {
+
+       /**
+        * Returns new Protocol Connection object. The rest of the attributes are
+        * protocol specific.
+        * @param address to be bind
+        * @return new Protocol Connection.
+        */
+       ProtocolConnection createProtocolConnection(final InetSocketAddress address);
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolInputStream.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolInputStream.java
new file mode 100644 (file)
index 0000000..060eb38
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+
+/**
+ * Data stream interface between Protocol Message and byte array, that represents this message as Java object. Used by
+ * the Dispatcher.
+ */
+public interface ProtocolInputStream {
+
+       /**
+        * Check availability of a message in underlying input stream. A message is available when there are more or the
+        * same amount of bytes in the stream as the message length is specified in message header. If there are not enough
+        * bytes for the message or even to read a message header, return false. Needs to be synchronized.
+        *
+        * @return true if there are enough bytes to read a message false if there are not enough bytes to read a message or
+        *         a message header.
+        *
+        * @throws IOException this exception may be thrown when "impossible" protocol buffering conditions occur.
+        *         Examples include: we are attempting to wait for more data than is theoretically possible (e.g. framing
+        *         error), peer is attempting to make us buffer more data than possible to accomodate (2G chunk), etc.
+        */
+       public boolean isMessageAvailable() throws IOException;
+
+       /**
+        * If there are enough bytes in the underlying stream, parse the message. Blocking, till there are enough bytes to
+        * read, therefore the call of method isMessageAvailable() is suggested first. Needs to be synchronized.
+        *
+        * @return protocol specific message
+        *
+        * @throws DeserializerException if the parsing was not successful due to syntax error
+        * @throws IOException if there was problem with extracting bytes from the stream
+        * @throws DocumentedException if the parsing was not successful
+        */
+       public ProtocolMessage getMessage() throws DeserializerException, IOException, DocumentedException;
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolInputStreamFactory.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolInputStreamFactory.java
new file mode 100644 (file)
index 0000000..8ee37d6
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.PipedInputStream;
+
+/**
+ * Factory for creating Protocol input streams. Should be implemented to return protocol
+ * specific input stream.
+ */
+public interface ProtocolInputStreamFactory {
+
+       /**
+        * Creates and returns protocol input stream.
+        * @param pis underlying piped input stream
+        * @param pmf protocol message factory
+        * @return protocol specific input stream
+        */
+       ProtocolInputStream getProtocolInputStream(PipedInputStream pis, ProtocolMessageFactory pmf);
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolMessage.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolMessage.java
new file mode 100644 (file)
index 0000000..aa9caa6
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.Serializable;
+
+/**
+ * Marker interface. Serves as a general concept of protocol message, smallest unit of
+ * information exchanged in a protocol. Classes in common-protocol work only with this
+ * type of message, so that the rest of the module can be used without knowing specifics
+ * of underlying protocol. Each implemented protocol either has some abstract class in
+ * its API that represents abstract protocol specific message and implements this interface
+ * or has only specific protocol messages and uses this interface directly.
+ *
+ * Example:
+ *
+ * public abstract SpecificProtocolMessage implements ProtocolMessage { .. }
+ *
+ * public class SpecificOpenMessage extends SpecificProtocolMessage { .. }
+ */
+public interface ProtocolMessage extends Serializable {
+
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolMessageFactory.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolMessageFactory.java
new file mode 100644 (file)
index 0000000..df8a062
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+/**
+ * Interface for factory for parsing and serializing protocol specific
+ * messages. Needs to be implemented by a protocol specific message
+ * factory. The methods put/parse should delegate parsing to specific
+ * message parsers, e.g. OpenMessageParser etc.
+ */
+public interface ProtocolMessageFactory {
+
+       /**
+        * Parses message from byte array. Requires specific protocol message
+        * header object to parse the header.
+        * @param bytes byte array from which the message will be parsed
+        * @param msgHeader protocol specific message header to parse the header
+        * @return specific protocol message
+        * @throws DeserializerException if some parsing error occurs
+        * @throws DocumentedException if some documented error occurs
+        */
+       public ProtocolMessage parse(final byte[] bytes, final ProtocolMessageHeader msgHeader) throws DeserializerException, DocumentedException;
+
+       /**
+        * Serializes protocol specific message to byte array.
+        * @param msg message to be serialized.
+        * @return byte array resulting message
+        */
+       public byte[] put(final ProtocolMessage msg);
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolMessageHeader.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolMessageHeader.java
new file mode 100644 (file)
index 0000000..2df1d78
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+/**
+ * Interface common for each protocol message header. Needs to be
+ * implemented by a specific protocol.
+ */
+public interface ProtocolMessageHeader {
+
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolOutputStream.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolOutputStream.java
new file mode 100644 (file)
index 0000000..7b6f1c6
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayDeque;
+import java.util.Queue;
+
+/**
+ * Data stream interface between ProtocolMessage and byte array,
+ * that represents this message in serialized form. Its instance
+ * needs to be present in protocol specific session, to allow
+ * sending messages from the session via the put() method.
+ */
+public final class ProtocolOutputStream {
+
+       /**
+        * List of Buffers whose content needs to be written to socket.
+        */
+       private final Queue<ByteBuffer> pendingData = new ArrayDeque<ByteBuffer>();
+
+       /**
+        * Assumes that the message is valid (that you cannot create an invalid
+        * message from API). Serializes given messages to byte array, converts this
+        * byte array to byteBuffer and adds it to List.
+        * @param message message to be written
+        * @param factory protocol specific message factory
+        */
+       public void putMessage(final ProtocolMessage message, final ProtocolMessageFactory factory) {
+               final byte[] bytes = factory.put(message);
+               if (bytes == null) {
+                       throw new IllegalArgumentException("Message parsed to null.");
+               }
+               synchronized (this.pendingData) {
+                       this.pendingData.add(ByteBuffer.wrap(bytes));
+               }
+       }
+
+       /**
+        * Used by PCEPDispatcher to retrieve the data that needs to be written to
+        * socket.
+        *
+        * @return data that needs to be written to socket
+        */
+       Queue<ByteBuffer> getBuffers() {
+               return this.pendingData;
+       }
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolServer.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolServer.java
new file mode 100644 (file)
index 0000000..d7860f0
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.channels.ServerSocketChannel;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Timer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+
+/**
+ * Representation of a server, created by {@link Dispatcher}. Should be extended by a protocol specific server
+ * implementation.
+ */
+public class ProtocolServer implements SessionParent {
+
+       private static final Logger logger = LoggerFactory.getLogger(ProtocolServer.class);
+
+       private static final int SESSIONS_LIMIT = 255;
+
+       private final InetSocketAddress serverAddress;
+
+       private final ServerSocketChannel channel;
+
+       private final ProtocolConnectionFactory connectionFactory;
+       private final ProtocolSessionFactory sessionFactory;
+       private final ProtocolInputStreamFactory inputStreamFactory;
+
+       /**
+        * Maps clients of this server to their address. The client is represented as PCEP session. Used BiMap for
+        * implementation to allow easy manipulation with both InetSocketAddress and PCEPSessionImpl representing a key.
+        */
+       private final BiMap<InetSocketAddress, ProtocolSession> sessions;
+
+       private final Map<InetSocketAddress, Integer> sessionIds;
+
+       private final DispatcherImpl dispatcher;
+
+       /**
+        * Creates a Protocol server.
+        *
+        * @param dispatcher Dispatcher
+        * @param address address to which this server is bound
+        * @param connectionFactory factory for connection specific properties
+        * @param channel server socket channel
+        * @param sessionFactory factory for sessions
+        * @param inputStreamFactory factory for input streams
+        */
+       public ProtocolServer(final DispatcherImpl dispatcher, final InetSocketAddress address, final ServerSocketChannel channel,
+                       final ProtocolConnectionFactory connectionFactory, final ProtocolSessionFactory sessionFactory,
+                       final ProtocolInputStreamFactory inputStreamFactory) {
+               this.dispatcher = dispatcher;
+               this.serverAddress = address;
+               this.channel = channel;
+               this.sessions = HashBiMap.create();
+               this.connectionFactory = connectionFactory;
+               this.sessionFactory = sessionFactory;
+               this.inputStreamFactory = inputStreamFactory;
+               this.sessionIds = new HashMap<InetSocketAddress, Integer>();
+       }
+
+       /**
+        * Creates a session. This method is called after the server accepts incoming client connection. A session is
+        * created for each client. If a session for a client (represented by the address) was already created, return this,
+        * else create a new one.
+        *
+        * @param clientAddress IP address of the client
+        * @param timer Timer common for all sessions
+        * @return new or existing PCEPSession
+        * @see <a href="http://tools.ietf.org/html/rfc5440#appendix-A">RFC</a>
+        */
+       public ProtocolSession createSession(final Timer timer, final InetSocketAddress clientAddress) {
+               ProtocolSession session = null;
+               if (this.sessions.containsKey(clientAddress)) { // when the session is created, the key is the InetSocketAddress
+                       session = this.sessions.get(clientAddress);
+                       if (compareTo(this.serverAddress.getAddress(), clientAddress.getAddress()) > 0) {
+                               try {
+                                       session.close();
+                               } catch (final IOException e) {
+                                       logger.error("Session {} could not be closed.", session);
+                               }
+                       }
+               } else {
+                       final int sessionId = getNextId(this.sessionIds.get(clientAddress), SESSIONS_LIMIT - 1);
+                       session = this.sessionFactory.getProtocolSession(this, timer, this.connectionFactory.createProtocolConnection(clientAddress),
+                                       sessionId);
+                       this.sessionIds.put(clientAddress, sessionId);
+               }
+               this.sessions.put(clientAddress, session);
+               return session;
+       }
+
+       ProtocolInputStream createInputStream(final PipedInputStream pis, final ProtocolMessageFactory pmf) {
+               return this.inputStreamFactory.getProtocolInputStream(pis, pmf);
+       }
+
+       /**
+        * Returns server address.
+        *
+        * @return server address
+        */
+       public InetSocketAddress getAddress() {
+               return this.serverAddress;
+       }
+
+       @Override
+       public synchronized void close() throws IOException {
+               for (final Entry<InetSocketAddress, ProtocolSession> s : this.sessions.entrySet()) {
+                       s.getValue().close();
+               }
+               this.sessions.clear();
+               this.dispatcher.removeServer(this);
+               this.channel.close();
+               logger.debug("Server {} closed.", this);
+       }
+
+       @Override
+       public synchronized void onSessionClosed(final ProtocolSession session) {
+               this.sessions.inverse().remove(session); // when the session is closed, the key is the instance of the session
+               this.dispatcher.closeSessionSockets(session);
+       }
+
+       @Override
+       public void checkOutputBuffer(final ProtocolSession session) {
+               this.dispatcher.checkOutputBuffer(session);
+       }
+
+       private static int getNextId(Integer lastId, final int maxId) {
+               return (lastId == null || maxId == lastId) ? 0 : ++lastId;
+       }
+
+       /**
+        * Compares byte array representations of two InetAddresses.
+        *
+        * @param addrOne
+        * @param addrTwo
+        * @throws IllegalArgumentException if InetAddresses don't belong to the same subclass of InetAddress.
+        * @return 1 if addrOne is greater than addrTwo, 0 if they are the same, -1 if addrOne is lower than addrTwo
+        */
+       private static int compareTo(final InetAddress addrOne, final InetAddress addrTwo) {
+               if ((addrOne instanceof Inet4Address && addrOne instanceof Inet6Address)
+                               || (addrOne instanceof Inet6Address && addrOne instanceof Inet4Address)) {
+                       throw new IllegalArgumentException("Cannot compare InetAddresses. They both have to be the same subclass of InetAddress.");
+               }
+               final byte[] byteOne = addrOne.getAddress();
+               final byte[] byteTwo = addrTwo.getAddress();
+               for (int i = 0; i < byteOne.length; i++) {
+                       if (byteOne[i] > byteTwo[i])
+                               return 1;
+                       else if (byteOne[i] < byteTwo[i])
+                               return -1;
+               }
+               return 0;
+       }
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSession.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSession.java
new file mode 100644 (file)
index 0000000..3646a79
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+/**
+ * Protocol Session represents the finite state machine in underlying
+ * protocol, including timers and its purpose is to create a connection
+ * between server and client. Session is automatically started, when TCP
+ * connection is created, but can be stopped manually.
+ * If the session is up, it has to redirect messages to/from user.
+ * Handles also malformed messages and unknown requests.
+ *
+ * This interface should be implemented by a final class representing
+ * a protocol specific session.
+ */
+public interface ProtocolSession extends Closeable {
+
+       /**
+        * Starts the session. This method should be used only internally by
+        * the Dispatcher.
+        */
+       public void startSession();
+
+       /**
+        * Returns underlying output stream to provide writable stream to the
+        * Dispatcher.
+        * @return underlying protocol specific output stream
+        */
+       public ProtocolOutputStream getStream();
+
+       /**
+        * Handles incoming message (parsing, reacting if necessary).
+        * @param msg incoming message
+        */
+       public void handleMessage(final ProtocolMessage msg);
+
+       /**
+        * Handles malformed message when a deserializer exception occurred.
+        * The handling might be different from when a documented exception
+        * is thrown.
+        * @param e deserializer exception that occurred
+        */
+       public void handleMalformedMessage(final DeserializerException e);
+
+       /**
+        * Handles malformed message when a documented exception occurred.
+        * The handling might be different from when a deserializer exception
+        * is thrown.
+        * @param e documented exception that occurred
+        */
+       public void handleMalformedMessage(final DocumentedException e);
+
+       /**
+        * Called when reached the end of input stream while reading.
+        */
+       public void endOfInput();
+
+       /**
+        * Getter for message factory
+        * @return protocol specific message factory
+        */
+       public ProtocolMessageFactory getMessageFactory();
+
+       /**
+        * Session is notified about the connection not being
+        * established successfully.
+        *
+        * @param e IOException that was the cause of
+        * failed connection.
+        */
+       public void onConnectionFailed(final IOException e);
+
+       /**
+        * Returns the maximum message size (in bytes) for purposes of dispatcher
+        * buffering -- the dispatcher allocates a buffer this big, and if it gets
+        * full without making decoding progress, the dispatcher terminates the
+        * session.
+        * 
+        * @return maximum message size
+        */
+       public int maximumMessageSize();
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionFactory.java b/framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionFactory.java
new file mode 100644 (file)
index 0000000..36d4650
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.util.Timer;
+
+/**
+ * Factory for generating Protocol Sessions. This class should be extended to
+ * return protocol specific session.
+ */
+public interface ProtocolSessionFactory {
+
+       /**
+        * Creates and returns protocol specific session.
+        * @param parent SessionParent
+        * @param timer Timer
+        * @param connection connection attributes
+        * @param sessionId session identifier
+        * @return new session
+        */
+       public ProtocolSession getProtocolSession(SessionParent parent, Timer timer, ProtocolConnection connection, int sessionId);
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SSLSelectableChannel.java b/framework/src/main/java/org/opendaylight/protocol/framework/SSLSelectableChannel.java
new file mode 100644 (file)
index 0000000..85e9a99
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+/**
+ * As in order to work with SSLSelectionKey, a channel needs to implement
+ * this interface. It is used to determine SSL progress and update interestOps
+ * of underlying channel.
+ */
+interface SSLSelectableChannel {
+       /**
+        * Return the events which the underlying channel should be selected for,
+        * based on what the user would like to see from us.
+        * 
+        * @param ops user's interest ops
+        * @return Calculated interest ops, including internal needs
+        */
+       public int computeInterestOps(final int ops);
+
+       /**
+        * Return a freshly-calculated operations which the channel is ready to
+        * make progress on.
+        * 
+        * @return Calculated ready ops
+        */
+       public int computeReadyOps();
+}
+
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SSLSelectionKey.java b/framework/src/main/java/org/opendaylight/protocol/framework/SSLSelectionKey.java
new file mode 100644 (file)
index 0000000..12fb474
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectionKey;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class SSLSelectionKey extends AbstractSelectionKey {
+       private static final Logger logger = LoggerFactory.getLogger(SSLSelectionKey.class);
+       private final SelectableChannel channel;
+       private final Selector selector;
+       private final SelectionKey key;
+       private int ops = 0, readyOps = 0;
+
+       SSLSelectionKey(final Selector selector, final SelectionKey key, final SelectableChannel channel) {
+               this.selector = selector;
+               this.channel = channel;
+               this.key = key;
+       }
+
+       @Override
+       public SelectableChannel channel() {
+               return channel;
+       }
+
+       @Override
+       public int interestOps() {
+               return ops;
+       }
+
+       @Override
+       public SelectionKey interestOps(final int ops) {
+               this.ops = ops;
+               return this;
+       }
+
+       @Override
+       public int readyOps() {
+               return readyOps;
+       }
+
+       @Override
+       public Selector selector() {
+               return selector;
+       }
+
+       void cancelSlave() {
+               key.cancel();
+       }
+
+       void updateInterestOps() {
+               int newOps = ops;
+
+               if (channel instanceof SSLSocketChannel) {
+                       newOps = ((SSLSocketChannel)channel).computeInterestOps(ops);
+               } else if (channel instanceof SSLServerSocketChannel) {
+                       newOps = ((SSLServerSocketChannel)channel).computeInterestOps(ops);
+               }
+
+               logger.trace("Updating interestOps to {} (before SSL={})", newOps, ops);
+
+               // FIXME: is this check sufficient?
+               if (key.isValid())
+                       key.interestOps(newOps);
+       }
+
+       boolean preselectReady() {
+               final int newReadyOps;
+
+               // FIXME: abstract out interface
+               if (channel instanceof SSLSocketChannel) {
+                       final SSLSocketChannel sc = (SSLSocketChannel)channel;
+                       newReadyOps = sc.computeReadyOps();
+
+                       if (sc.hasParent()) {
+                               logger.trace("Child key, ready {}", newReadyOps);
+                               if ((newReadyOps & SelectionKey.OP_CONNECT) != 0) {
+                                       try {
+                                               if (sc.finishConnect()) {
+                                                       this.cancel();
+                                                       return true;
+                                               } else
+                                                       logger.trace("finishConnect indicated non-connect after poll. Possible leak.");
+                                       } catch (IOException e) {
+                                               logger.trace("Failed to establish child socket", e);
+                                               this.cancel();
+                                       }
+                               }
+                               return false;
+                       }
+               } else if (channel instanceof SSLServerSocketChannel) {
+                       newReadyOps = ((SSLServerSocketChannel)channel).computeReadyOps();
+               } else
+                       newReadyOps = 0;
+
+               logger.trace("Preselect: ready {} interest {} (A: {} R: {} W: {})",
+                               newReadyOps, ops, SelectionKey.OP_CONNECT, SelectionKey.OP_READ, SelectionKey.OP_WRITE);
+               return (newReadyOps & ops) != 0;
+       }
+
+       boolean updateReadyOps() {
+               int newReadyOps = 0;
+               if (channel instanceof SSLServerSocketChannel) {
+                       newReadyOps = ((SSLServerSocketChannel)channel).computeReadyOps();
+               } else if (channel instanceof SSLSocketChannel) {
+                       final SSLSocketChannel sc = (SSLSocketChannel)channel;
+
+                       // Do not report events for internal channels
+                       if (!sc.hasParent())
+                               newReadyOps = sc.computeReadyOps();
+               } else {
+                       try {
+                               newReadyOps = key.readyOps();
+                       } catch (CancelledKeyException e) {
+                               logger.trace("Encountered cancelled key, ignoring", e);
+                       }
+               }
+
+               if (readyOps == newReadyOps)
+                       return false;
+
+               logger.trace("Updating readyOps from {} to {}", readyOps, newReadyOps);
+               readyOps = newReadyOps;
+               return true;
+       }
+}
+
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SSLSelector.java b/framework/src/main/java/org/opendaylight/protocol/framework/SSLSelector.java
new file mode 100644 (file)
index 0000000..68e4bc1
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.util.Collections;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.RemoveOnlySet;
+import com.google.common.collect.Sets;
+
+class SSLSelector extends AbstractSelector {
+       private static final Logger logger = LoggerFactory.getLogger(SSLSelector.class);
+       private final Set<SelectionKey> selectedKeys = Sets.newHashSet();
+       private final Set<SelectionKey> keys = Sets.newCopyOnWriteArraySet();
+
+       private final Set<SelectionKey> guardedSelectedKeys = RemoveOnlySet.wrap(selectedKeys);
+       private final Set<SelectionKey> guardedKeys = Collections.unmodifiableSet(keys);
+       private final Selector selector;
+       private boolean closed = false;
+
+       SSLSelector(final Selector selector) throws IOException {
+               super(selector.provider());
+               this.selector = selector;
+       }
+
+       @Override
+       protected void implCloseSelector() throws IOException {
+               // Make sure selection won't block
+               selector.wakeup();
+
+               synchronized (this) {
+                       if (!closed) {
+                               closed = true;
+                               for (SelectionKey k : keys)
+                                       k.cancel();
+
+                               keys.clear();
+                               selector.close();
+                       }
+               }
+       }
+
+       @Override
+       protected synchronized SelectionKey register(final AbstractSelectableChannel ch, final int ops, final Object att) {
+               ensureOpen();
+
+               final AbstractSelectableChannel slave;
+               if (ch instanceof SSLServerSocketChannel)
+                       slave = ((SSLServerSocketChannel)ch).channel;
+               else if (ch instanceof SSLSocketChannel)
+                       slave = ((SSLSocketChannel)ch).channel;
+               else
+                       slave = ch;
+
+               logger.trace("Register channel {} slave {} with ops {}", ch, slave, ops);
+
+               final SelectionKey key;
+               try {
+                       key = new SSLSelectionKey(this, slave.register(selector, 0, null), ch);
+               } catch (ClosedChannelException e) {
+                       throw new IllegalStateException("Slave selector found the channel closed", e);
+               }
+               key.interestOps(ops);
+               key.attach(att);
+               keys.add(key);
+               return key;
+       }
+
+       @Override
+       public synchronized Set<SelectionKey> keys() {
+               ensureOpen();
+               return guardedKeys;
+       }
+
+       private void ensureOpen() {
+               if (closed)
+                       throw new ClosedSelectorException();
+       }
+
+       private int afterSelect() {
+               logger.trace("Running afterSelect");
+               int ret = 0;
+
+               final Set<SelectionKey> ck = cancelledKeys();
+               synchronized (ck) {
+                       selectedKeys.removeAll(ck);
+
+                       for (final SelectionKey k : keys) {
+                               final boolean updated = ((SSLSelectionKey)k).updateReadyOps();
+                               if ((k.readyOps() & k.interestOps()) != 0) {
+                                       selectedKeys.add(k);
+                                       if (updated)
+                                               ++ret;
+                               } else
+                                       selectedKeys.remove(k);
+                       }
+               }
+
+               return ret;
+       }
+
+       private boolean beforeSelect() {
+               logger.trace("Running beforeSelect");
+
+               final Set<SelectionKey> ck = cancelledKeys();
+               synchronized (ck) {
+                       for (final SelectionKey k : ck)
+                               ((SSLSelectionKey)k).cancelSlave();
+                       selectedKeys.removeAll(ck);
+                       keys.removeAll(ck);
+                       ck.clear();
+
+                       for (final SelectionKey k : keys) {
+                               final SSLSelectionKey sk = (SSLSelectionKey)k;
+                               if (sk.preselectReady()) {
+                                       logger.trace("Key {} ready in preselect", k);
+                                       return true;
+                               } else
+                                       sk.updateInterestOps();
+                       }
+               }
+
+               return false;
+       }
+
+       @Override
+       public synchronized int select() throws IOException {
+               return select(0);
+       }
+
+       @Override
+       public synchronized int select(final long timeout) throws IOException {
+               ensureOpen();
+
+               if (!beforeSelect()) {
+                       try {
+                               begin();
+                               selector.select(timeout);
+                       } finally {
+                               end();
+                       }
+               }
+               return afterSelect();
+       }
+
+       @Override
+       public synchronized int selectNow() throws IOException {
+               ensureOpen();
+
+               if (!beforeSelect())
+                       selector.selectNow();
+               return afterSelect();
+       }
+
+       @Override
+       public synchronized Set<SelectionKey> selectedKeys() {
+               ensureOpen();
+               return guardedSelectedKeys;
+       }
+
+       @Override
+       public Selector wakeup() {
+               logger.trace("Running wakeup");
+               selector.wakeup();
+               return this;
+       }
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SSLServerSocketChannel.java b/framework/src/main/java/org/opendaylight/protocol/framework/SSLServerSocketChannel.java
new file mode 100644 (file)
index 0000000..cfccf08
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+import javax.net.ssl.SSLContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Queues;
+
+/**
+ * SSL-enabled equivalent of ServerSocketChannel. This class uses a backend
+ * ServerSocketChannel to implement network functionality. Each instance is
+ * bound to a SSLContext, which is used to create a per-connection SSLEngine,
+ * which is encapsulated into the returned SSLSocketChannel.
+ */
+final class SSLServerSocketChannel extends ServerSocketChannel implements SSLSelectableChannel {
+       private static final Logger logger = LoggerFactory.getLogger(SSLServerSocketChannel.class);
+       private final Queue<SocketChannel> newChannels = Queues.newArrayDeque();
+       private final SSLContext context;
+       private final Executor executor;
+       private final Selector selector;
+       private boolean closed = false;
+
+       protected final ServerSocketChannel channel;
+
+       private SSLServerSocketChannel(final Selector selector, final ServerSocketChannel channel, final SSLContext context, final Executor executor) {
+               super(channel.provider());
+               this.selector = selector;
+               this.executor = executor;
+               this.channel = channel;
+               this.context = context;
+       }
+
+       public static SSLServerSocketChannel open(final Selector selector, final SSLContext context, final Executor executor) throws IOException {
+               return new SSLServerSocketChannel(selector, ServerSocketChannel.open(), context, executor);
+       }
+
+       @Override
+       public final synchronized SocketChannel accept() {
+               return newChannels.poll();
+       }
+
+       @Override
+       public ServerSocket socket() {
+               // We do not support this operation, everyone should use Java 7 interfaces
+               throw new UnsupportedOperationException("SSLSocketChannel does not provide a fake Socket implementation");
+       }
+
+       @Override
+       protected synchronized void implCloseSelectableChannel() throws IOException {
+               closed = true;
+               while (!newChannels.isEmpty()) {
+                       final SocketChannel c = newChannels.poll();
+                       try {
+                               c.close();
+                       } catch (IOException e) {
+                               logger.trace("Failed to close a queued channel", e);
+                       }
+               }
+               channel.close();
+       }
+
+       @Override
+       protected void implConfigureBlocking(final boolean block) throws IOException {
+               channel.configureBlocking(block);
+       }
+
+       @Override
+       public final synchronized int computeInterestOps(final int ops) {
+               // We are always interested in accepting stuff
+               return SelectionKey.OP_ACCEPT;
+       }
+
+       private void performIO() {
+               while (true) {
+                       final SocketChannel newchan;
+                       try {
+                               newchan = channel.accept();
+                               if (newchan == null)
+                                       break;
+                       } catch (IOException e) {
+                               logger.trace("Underlying accept() failed", e);
+                               return;
+                       }
+
+                       try {
+                               final SocketChannel sc;
+                               try {
+                                       sc = SSLSocketChannel.open(newchan, context, executor, this);
+                               } catch (IOException e) {
+                                       logger.trace("Failed to create SSL channel", e);
+                                       newchan.close();
+                                       continue;
+                               }
+
+                               try {
+                                       sc.configureBlocking(false);
+                                       sc.register(selector, SelectionKey.OP_CONNECT, null);
+                               } catch (IOException e) {
+                                       logger.trace("Failed to register SSL channel", e);
+                                       sc.close();
+                                       continue;
+                               }
+
+                               logger.trace("Accepted new connection, channel is {} backend {}", sc, newchan);
+                       } catch (IOException e1) {
+                               logger.trace("Failed to close failed channel", e1);
+                       }
+               }
+       }
+
+       @Override
+       public final synchronized int computeReadyOps() {
+               if (closed)
+                       return 0;
+
+               performIO();
+
+               // We need to be non-closed and have enqueue channels to be ready
+               if (!closed && !newChannels.isEmpty())
+                       return SelectionKey.OP_ACCEPT;
+               return 0;
+       }
+
+       /**
+        * Enqueue a freshly-established child channel for reporting as
+        * a ready-to-accept connection.
+        *
+        * @param channel Fresh channel, expected to be in connected state
+        */
+       final synchronized void addNewChannel(final SocketChannel channel) {
+               if (closed) {
+                       try {
+                               channel.close();
+                       } catch (IOException e) {
+                               logger.trace("Failed to close a queued channel", e);
+                       }
+               } else
+                       newChannels.add(channel);
+       }
+
+       @Override
+       public SocketAddress getLocalAddress() throws IOException {
+               return channel.getLocalAddress();
+       }
+
+       @Override
+       public <T> T getOption(SocketOption<T> name) throws IOException {
+               return channel.getOption(name);
+       }
+
+       @Override
+       public Set<SocketOption<?>> supportedOptions() {
+               return channel.supportedOptions();
+       }
+
+       @Override
+       public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
+               channel.bind(local, backlog);
+               return this;
+       }
+
+       @Override
+       public <T> ServerSocketChannel setOption(SocketOption<T> name, T value) throws IOException {
+               channel.setOption(name, value);
+               return this;
+       }
+}
+
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SSLSocketChannel.java b/framework/src/main/java/org/opendaylight/protocol/framework/SSLSocketChannel.java
new file mode 100644 (file)
index 0000000..bdf7eb4
--- /dev/null
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/*
+ * Base class for an SSL-enabled socket channel. It is completed as
+ * SSLSocketChannel in one of the two Java version-specific files.
+ */
+final class SSLSocketChannel extends SocketChannel implements SSLSelectableChannel {
+       private enum InternalState {
+               /**
+                * Freshly created socket. Must be connected.
+                */
+               IDLE,
+               /**
+                * Underlying TCP connection is being established.
+                */
+               CONNECTING,
+               /**
+                * Underlying TCP connection is established, we are currently
+                * negotiating SSL session parameters.
+                */
+               NEGOTIATING,
+               /**
+                * Connection attempt has been resolved, we need the user
+                * to call finishConnect().
+                */
+               CONNECT_RESOLVED,
+               /**
+                * We have notified the user that the connection has failed,
+                * all we need to do is cleanup resources.
+                */
+               CONNECT_FAILED,
+               /**
+                * We have notified user that the connection has been
+                * established and the channel is fully operational.
+                */
+               CONNECTED,
+               /**
+                * We are closing down the channel. From user's perspective
+                * it is already dead, we just need to cleanup.
+                */
+               CLOSING,
+               /**
+                * The channel has been closed and all resources released.
+                */
+               CLOSED,
+       }
+
+       private static final Logger logger = LoggerFactory.getLogger(SSLSocketChannel.class);
+       private SSLServerSocketChannel parent;
+       final SocketChannel channel;
+       final SSLEngine engine;
+
+       private final ByteBuffer fromNetwork, toNetwork, toUser;
+       private final ByteBuffer empty = ByteBuffer.allocate(0);
+       private final Executor executor;
+       private IOException connectResult = null;
+       private IOException writeFailed = null, closeFailed = null;
+       private boolean readDone = false;
+       private boolean closedInput = false, closedOutput = false;
+       private InternalState state;
+
+       private SSLSocketChannel(final SocketChannel channel, final SSLEngine engine,
+                       final Executor executor, final SSLServerSocketChannel parent) throws SSLException {
+               super(channel.provider());
+               this.executor = executor;
+               this.channel = channel;
+               this.parent = parent;
+               this.engine = engine;
+
+               final SSLSession session = engine.getSession();
+               fromNetwork = ByteBuffer.allocate(session.getPacketBufferSize());
+               fromNetwork.limit(0);
+               toNetwork = ByteBuffer.allocate(session.getPacketBufferSize());
+               toNetwork.limit(0);
+               toUser = ByteBuffer.allocate(session.getApplicationBufferSize());
+
+               if (parent != null) {
+                       engine.setUseClientMode(false);
+                       engine.setWantClientAuth(true);
+                       engine.setNeedClientAuth(false);
+                       engine.beginHandshake();
+                       state = InternalState.NEGOTIATING;
+               } else
+                       state = InternalState.IDLE;
+       }
+
+       public static SSLSocketChannel open(final SocketChannel channel, final SSLContext context,
+                       final Executor executor, final SSLServerSocketChannel parent) throws IOException {
+
+               return new SSLSocketChannel(channel, context.createSSLEngine(), executor, parent);
+       }
+
+       @Override
+       public synchronized boolean connect(final SocketAddress remote) throws IOException {
+               switch (state) {
+               case CLOSED:
+               case CLOSING:
+               case CONNECT_FAILED:
+                       throw new ClosedChannelException();
+               case CONNECTED:
+                       throw new AlreadyConnectedException();
+               case CONNECTING:
+               case CONNECT_RESOLVED:
+               case NEGOTIATING:
+                       throw new ConnectionPendingException();
+               case IDLE:
+                       if (channel.connect(remote)) {
+                               engine.setUseClientMode(true);
+                               engine.beginHandshake();
+                               state = InternalState.NEGOTIATING;
+                       } else
+                               state = InternalState.CONNECTING;
+                       return false;
+               }
+
+               throw new IllegalStateException("Unhandled state " + state);
+       }
+
+       @Override
+       public synchronized boolean finishConnect() throws IOException {
+               logger.trace("Attempting to finish connection in state {}", state);
+
+               switch (state) {
+               case CLOSED:
+               case CLOSING:
+               case CONNECT_FAILED:
+                       throw new ClosedChannelException();
+               case CONNECTED:
+                       return true;
+               case CONNECT_RESOLVED:
+                       if (connectResult != null) {
+                               state = InternalState.CONNECT_FAILED;
+                               try {
+                                       logger.trace("Internal close after failed connect");
+                                       close();
+                               } catch (IOException e) {
+                                       logger.trace("Failed to invoked internal close", e);
+                               }
+                               throw connectResult;
+                       }
+
+                       state = InternalState.CONNECTED;
+                       if (parent != null) {
+                               parent.addNewChannel(this);
+                               parent = null;
+                       }
+                       return true;
+               case CONNECTING:
+               case NEGOTIATING:
+                       return false;
+               case IDLE:
+                       throw new NoConnectionPendingException();
+               }
+
+               throw new IllegalStateException("Unhandled state " + state);
+       }
+
+       @Override
+       public synchronized boolean isConnected() {
+               return state == InternalState.CONNECTED;
+       }
+
+       @Override
+       public synchronized boolean isConnectionPending() {
+               switch (state) {
+               case CONNECTING:
+               case CONNECT_RESOLVED:
+               case NEGOTIATING:
+                       return true;
+               default:
+                       return false;
+               }
+       }
+
+       private int readNetwork() throws IOException {
+               fromNetwork.compact();
+
+               final int ret;
+               try {
+                       ret = channel.read(fromNetwork);
+               } finally {
+                       fromNetwork.flip();
+               }
+
+               logger.trace("Channel {} has input {} after {}", this, fromNetwork.remaining(), ret);
+               return ret;
+       }
+
+       private int writeNetwork() throws IOException {
+               toNetwork.flip();
+
+               final int ret;
+               try {
+                       ret = channel.write(toNetwork);
+               } finally {
+                       toNetwork.compact();
+               }
+
+               logger.trace("Channel {} has output {} after {}", this, toNetwork.remaining(), ret);
+               return ret;
+       }
+
+       private void checkChannelState() throws IOException {
+               switch (state) {
+               case CLOSED:
+               case CLOSING:
+               case CONNECT_FAILED:
+                       throw new ClosedChannelException();
+               case CONNECTED:
+                       break;
+               case CONNECT_RESOLVED:
+               case CONNECTING:
+               case IDLE:
+               case NEGOTIATING:
+                       throw new NotYetConnectedException();
+               }
+       }
+
+       private boolean checkReadState() throws IOException {
+               checkChannelState();
+               return closedInput;
+       }
+
+       @Override
+       public synchronized int read(final ByteBuffer dst) throws IOException {
+               if (checkReadState())
+                       return -1;
+
+               /*
+                * If we have some data overflowed from negotiation, flush that
+                * first.
+                */
+               if (toUser.position() != 0) {
+                       logger.trace("toUser has {}", toUser.position());
+                       toUser.flip();
+
+                       final int xfer = Math.min(toUser.remaining(), dst.remaining());
+                       dst.put(toUser.array(), toUser.arrayOffset() + toUser.position(), xfer);
+                       toUser.position(toUser.position() + xfer);
+                       toUser.compact();
+                       return xfer;
+               }
+
+               // We have input data, unwrap it
+               if (fromNetwork.hasRemaining()) {
+                       final SSLEngineResult res = engine.unwrap(fromNetwork, dst);
+                       return res.bytesProduced();
+               }
+
+               // EOF on underlying stream, inform the engine
+               if (readDone)
+                       engine.closeInbound();
+
+               // SSL engine says there may be some more input
+               if (!engine.isInboundDone())
+                       return 0;
+
+               logger.trace("SSL engine indicates clean shutdown");
+               return -1;
+       }
+
+       @Override
+       public synchronized long read(final ByteBuffer[] dsts, final int offset, final int length) throws IOException {
+               if (checkReadState())
+                       return -1;
+
+               /*
+                * Search for the first buffer with available data and perform
+                * a single-buffer read into it. Not completely efficient, but
+                * does the work required.
+                */
+               for (int i = offset; i < length; ++i)
+                       if (dsts[i].remaining() != 0)
+                               return read(dsts[i]);
+
+               return 0;
+       }
+
+       @Override
+       public Socket socket() {
+               // We do not support this operation, everyone should use Java 7 interfaces
+               throw new UnsupportedOperationException("SSLSocketChannel does not provide a fake Socket implementation");
+       }
+
+       private void checkWriteState() throws IOException {
+               checkChannelState();
+
+               if (closedOutput)
+                       throw new ClosedChannelException();
+
+               if (writeFailed != null)
+                       throw writeFailed;
+       }
+
+       @Override
+       public synchronized int write(final ByteBuffer src) throws IOException {
+               checkWriteState();
+
+               final SSLEngineResult res = engine.wrap(src, toNetwork);
+               return res.bytesConsumed();
+       }
+
+       @Override
+       public synchronized long write(final ByteBuffer[] srcs, final int offset, final int length) throws IOException {
+               checkWriteState();
+
+               final SSLEngineResult res = engine.wrap(srcs, offset, length, toNetwork);
+               return res.bytesConsumed();
+       }
+
+       @Override
+       protected synchronized void implCloseSelectableChannel() throws IOException {
+               logger.trace("Closing channel in state {}", state);
+
+               switch (state) {
+               case CONNECTED:
+                       state = InternalState.CLOSING;
+                       engine.closeOutbound();
+                       break;
+               case CLOSED:
+               case CLOSING:
+                       // Nothing to do
+                       break;
+               case CONNECT_FAILED:
+               case CONNECT_RESOLVED:
+               case CONNECTING:
+               case IDLE:
+               case NEGOTIATING:
+                       state = InternalState.CLOSED;
+                       channel.close();
+                       break;
+               }
+       }
+
+       @Override
+       protected void implConfigureBlocking(final boolean block) throws IOException {
+               channel.configureBlocking(block);
+       }
+
+       @Override
+       public synchronized int computeInterestOps(int userOps) {
+               logger.trace("Interestops in state {} userOps {}", state, userOps);
+
+               int ret = 0;
+
+               switch (state) {
+               case CLOSED:
+               case CONNECT_FAILED:
+               case CONNECT_RESOLVED:
+               case IDLE:
+                       return 0;
+               case CLOSING:
+                       if (engine.isOutboundDone() && toNetwork.position() == 0)
+                               throw new IllegalStateException("Network flush completed, but still in CLOSING state");
+                       return SelectionKey.OP_WRITE;
+               case CONNECTING:
+                       return SelectionKey.OP_CONNECT;
+               case NEGOTIATING:
+                       userOps = 0;
+
+                       final HandshakeStatus st = engine.getHandshakeStatus();
+
+                       logger.trace("SSL Engine status {}", st);
+
+                       switch (st) {
+                       case NEED_UNWRAP:
+                               userOps = SelectionKey.OP_READ;
+                               break;
+                       case NEED_WRAP:
+                               userOps = SelectionKey.OP_WRITE;
+                               break;
+                       default:
+                               logger.trace("Unexpected SSLEngine handshake status {}", st);
+                               connectResult = new IOException("Unexpected SSLEngine handshake status " + st);
+                               connectResult.fillInStackTrace();
+                               state = InternalState.CONNECT_RESOLVED;
+                               return 0;
+                       }
+
+                       // Intentional fall through
+               case CONNECTED:
+                       if ((userOps & SelectionKey.OP_READ) != 0 && !fromNetwork.hasRemaining())
+                               ret |= SelectionKey.OP_READ;
+                       if ((userOps & SelectionKey.OP_WRITE) != 0 && !toNetwork.hasRemaining())
+                               ret |= SelectionKey.OP_WRITE;
+
+                       logger.trace("userOps {} fromNetwork {} toNetwork {} ret {}", userOps, fromNetwork.remaining(), toNetwork.remaining(), ret);
+                       return ret;
+               }
+
+               throw new IllegalStateException("Unhandled state " + state);
+       }
+
+       private void performIO() {
+               logger.trace("IO operations in state {}", state);
+
+               switch (state) {
+               case CLOSED:
+               case CONNECT_RESOLVED:
+               case IDLE:
+                       // Nothing to do
+                       break;
+               case CLOSING:
+                       boolean forceClose = false;
+                       if (!engine.isOutboundDone()) {
+                               try {
+                                       engine.wrap(empty, toNetwork);
+                               } catch (SSLException e) {
+                                       logger.trace("Failed to close down SSL engine outbound", e);
+                               }
+                       }
+
+                       if (toNetwork.position() != 0) {
+                               try {
+                                       writeNetwork();
+                               } catch (IOException e) {
+                                       logger.trace("Failed to flush outstanding buffers, forcing close", e);
+                                       forceClose = true;
+                               }
+                       }
+
+                       if (forceClose || (engine.isOutboundDone() && toNetwork.position() == 0)) {
+                               logger.trace("Completed state flush");
+                               state = InternalState.CLOSED;
+                               try {
+                                       channel.close();
+                               } catch (IOException e) {
+                                       logger.trace("Failed to close slave channel", e);
+                               }
+                       }
+                       break;
+               case CONNECT_FAILED:
+                       try {
+                               logger.trace("Invoking internal close after failure");
+                               close();
+                       } catch (IOException e) {
+                               logger.trace("Internal fail closed", e);
+                       }
+                       break;
+               case CONNECTED:
+                       try {
+                               if (!readDone && readNetwork() < 0) {
+                                       readDone = true;
+                                       try {
+                                               engine.closeInbound();
+                                       } catch (IOException e) {
+                                               logger.trace("TLS reported close error", e);
+                                               closeFailed = e;
+                                       }
+                               }
+                       } catch (IOException e) {
+                               logger.trace("Background read failed", e);
+                               readDone = true;
+                       }
+
+                       try {
+                               if (toNetwork.position() != 0)
+                                       writeNetwork();
+                       } catch (IOException e) {
+                               logger.trace("Background write failed", e);
+                               writeFailed = e;
+                               toNetwork.clear();
+                       }
+                       break;
+               case CONNECTING:
+                       try {
+                               if (channel.finishConnect()) {
+                                       engine.setUseClientMode(true);
+                                       engine.beginHandshake();
+                                       state = InternalState.NEGOTIATING;
+                               }
+                       } catch (IOException e) {
+                               logger.trace("Finished connection with error", e);
+                               connectResult = e;
+                               state = InternalState.CONNECT_RESOLVED;
+                       }
+                       break;
+               case NEGOTIATING:
+                       boolean needMore = true;
+
+                       do {
+                               final HandshakeStatus st = engine.getHandshakeStatus();
+                               if (st == HandshakeStatus.NEED_TASK) {
+                                       // Dispatch any blocking tasks that SSLEngine has for us.
+                                       while (true) {
+                                               final Runnable r = engine.getDelegatedTask();
+                                               if (r == null)
+                                                       break;
+
+                                               executor.execute(r);
+                                       }
+                                       continue;
+                               }
+
+                               try {
+                                       if (readNetwork() < 0) {
+                                               logger.trace("Unexpected end of stream during negotiation");
+                                               connectResult = new EOFException("Unexpected end-of-channel during SSL negotiation");
+                                               connectResult.fillInStackTrace();
+                                               state = InternalState.CONNECT_RESOLVED;
+                                               break;
+                                       }
+                                       writeNetwork();
+                               } catch (IOException e) {
+                                       logger.trace("IO error during SSL negotiation", e);
+                                       connectResult = e;
+                                       state = InternalState.CONNECT_RESOLVED;
+                                       break;
+                               }
+
+                               final SSLEngineResult res;
+                               try {
+                                       logger.trace("Status {} fromNetwork {} toNetwork {} toUser {}", st, fromNetwork.remaining(), toNetwork.remaining(), toUser.remaining());
+
+                                       if (st == HandshakeStatus.NEED_UNWRAP) {
+                                               // SSLEngine needs to read some data from the network
+                                               res = engine.unwrap(fromNetwork, toUser);
+                                               if (res.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW)
+                                                       needMore = false;
+                                       } else if (st == HandshakeStatus.NEED_WRAP) {
+                                               // SSLEngine needs to write some data to the network
+                                               res = engine.wrap(empty, toNetwork);
+                                               if (res.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW)
+                                                       needMore = false;
+                                       } else {
+                                               logger.trace("Unexpected state {} in SSL negotiation", engine.getHandshakeStatus());
+                                               connectResult = new IOException("Unexpected SSL negotiation state");
+                                               connectResult.fillInStackTrace();
+                                               state = InternalState.CONNECT_RESOLVED;
+                                               break;
+                                       }
+                               } catch (SSLException e) {
+                                       logger.trace("SSL negotiation failed", e);
+                                       connectResult = e;
+                                       state = InternalState.CONNECT_RESOLVED;
+                                       break;
+                               }
+
+                               logger.trace("SSL needMore {} result {}", needMore, res);
+
+                               if (res.getHandshakeStatus() == HandshakeStatus.FINISHED) {
+                                       final SSLSession s = engine.getSession();
+                                       logger.trace("SSL session established: {}", s);
+                                       state = InternalState.CONNECT_RESOLVED;
+                                       break;
+                               }
+                       } while (needMore);
+               }
+       }
+
+       @Override
+       public synchronized int computeReadyOps() {
+               performIO();
+
+               logger.trace("Readyops in state {}", state);
+
+               switch (state) {
+               case CLOSED:
+               case CLOSING:
+               case CONNECT_FAILED:
+               case CONNECTING:
+               case IDLE:
+               case NEGOTIATING:
+                       return 0;
+               case CONNECT_RESOLVED:
+                       return SelectionKey.OP_CONNECT;
+               case CONNECTED:
+                       int ret = 0;
+
+                       if (toNetwork.hasRemaining() || writeFailed != null)
+                               ret |= SelectionKey.OP_WRITE;
+                       if (fromNetwork.hasRemaining() || toUser.position() != 0)
+                               ret |= SelectionKey.OP_READ;
+
+                       return ret;
+               }
+
+               throw new IllegalStateException("Unhandled state " + state);
+       }
+
+       @Override
+       public SocketChannel bind(final SocketAddress local) throws IOException {
+               channel.bind(local);
+               return this;
+       }
+
+       @Override
+       public SocketAddress getLocalAddress() throws IOException {
+               return channel.getLocalAddress();
+       }
+
+       @Override
+       public SocketAddress getRemoteAddress() throws IOException {
+               return channel.getRemoteAddress();
+       }
+
+       @Override
+       public synchronized SocketChannel shutdownInput() throws IOException {
+               checkChannelState();
+
+               if (!closedInput) {
+                       closedInput = true;
+                       if (closeFailed != null)
+                               throw closeFailed;
+                       logger.debug("Socket {} input shut down", this);
+               }
+
+               return this;
+       }
+
+       @Override
+       public synchronized SocketChannel shutdownOutput() throws IOException {
+               checkChannelState();
+
+               if (!closedOutput) {
+                       closedOutput = true;
+                       engine.closeOutbound();
+                       logger.debug("Socket {} output shut down", this);
+               }
+
+               return this;
+       }
+
+       @Override
+       public <T> T getOption(SocketOption<T> name) throws IOException {
+               return channel.getOption(name);
+       }
+
+       @Override
+       public <T> SocketChannel setOption(SocketOption<T> name, T value) throws IOException {
+               channel.setOption(name, value);
+               return this;
+       }
+
+       @Override
+       public Set<SocketOption<?>> supportedOptions() {
+               return channel.supportedOptions();
+       }
+
+       synchronized boolean hasParent() {
+               return parent != null;
+       }
+}
+
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java b/framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java
new file mode 100644 (file)
index 0000000..5f52af7
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.util.EventListener;
+
+/**
+ *     Listener that receives session state informations. This interface should be
+ *  implemented by a protocol specific abstract class, that is extended by
+ *  a final class that implements the methods.
+ */
+public interface SessionListener extends EventListener {
+
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SessionListenerFactory.java b/framework/src/main/java/org/opendaylight/protocol/framework/SessionListenerFactory.java
new file mode 100644 (file)
index 0000000..542c4f8
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.net.InetAddress;
+
+/**
+ * Factory for generating Session Listeners. Used by a server. This interface should be
+ * implemented by a protocol specific abstract class, that is extended by
+ * a final class that implements the methods.
+ */
+public interface SessionListenerFactory {
+       /**
+        * Returns one session listener
+        * @param address serves as constraint, so that factory is able to
+        * return different listeners for different factories
+        * @return specific session listener
+        */
+       public SessionListener getSessionListener(final InetAddress address);
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SessionParent.java b/framework/src/main/java/org/opendaylight/protocol/framework/SessionParent.java
new file mode 100644 (file)
index 0000000..0088b23
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.Closeable;
+
+/**
+ * Interface that groups together the classes that can create a session (Dispatcher and Server). When a session
+ * is closing, it has to notify its parent about closing. Each parent keeps a Map of its sessions. When some session closes,
+ * it fires onSessionClosed event with its own instance as parameter and the parent of this session will remove it from his map.
+ */
+public interface SessionParent extends Closeable {
+
+       /**
+        * This listener method is called when a session that was created by a class implementing this interface,
+        * is closing. Implementation should remove corresponding session from its list of sessions.
+        * @param session a session that is closing
+        */
+       public void onSessionClosed(final ProtocolSession session);
+
+       /**
+        * This listener method is called when a session has produced some output and the parent needs to react to
+        * it.
+        * @param session a session that has produced output
+        */
+       public void checkOutputBuffer(final ProtocolSession session);
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SessionPreferences.java b/framework/src/main/java/org/opendaylight/protocol/framework/SessionPreferences.java
new file mode 100644 (file)
index 0000000..868b3ec
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+/**
+ * Marker interface to be implemented by underlying protocol. This object represents
+ * a DTO for all session characteristics, that are negotiated during the protocol
+ * handshake.
+ */
+public interface SessionPreferences {
+
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SessionPreferencesChecker.java b/framework/src/main/java/org/opendaylight/protocol/framework/SessionPreferencesChecker.java
new file mode 100644 (file)
index 0000000..ca38ea8
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+/**
+ * Interface to work with session preferences. They need to be
+ * checked during the establishment phase. If they are not
+ * acceptable a new proposal needs to be requested.
+ * This interface should be implemented by a protocol specific
+ * abstract class, that is extended by a final class that implements
+ * the methods.
+ */
+public interface SessionPreferencesChecker {
+
+       /**
+        * Checks session characteristics, if they are acceptable.
+        *
+        * @param openObj
+        *            storage for session characteristics
+        * @return true = acceptable, false = negotiable, null = unacceptable
+        * @throws DocumentedException when there is specific protocol error
+        * for rejecting the session characteristics
+        */
+       public Boolean checkSessionCharacteristics(final SessionPreferences openObj) throws DocumentedException;
+
+       /**
+        * In case of negotiable session characteristics, new ones are requested
+        * through this method.
+        *
+        * @param oldOpen old open object with unacceptable session characteristics
+        * @return
+        *      <li> new session characteristics wrapped in Open Object
+        *      <li> null if there are not available any different acceptable
+        * session characteristics
+        */
+       public SessionPreferences getNewProposal(final SessionPreferences oldOpen);
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SessionPreferencesCheckerFactory.java b/framework/src/main/java/org/opendaylight/protocol/framework/SessionPreferencesCheckerFactory.java
new file mode 100644 (file)
index 0000000..b1d7bbe
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.net.InetSocketAddress;
+
+/**
+ * Factory for generating Session preferences Checkers. Used by a server.
+ * This interface should be implemented by a protocol specific abstract class,
+ * that is extended by a final class that implements the methods.
+ */
+public interface SessionPreferencesCheckerFactory {
+
+       /**
+        * Returns one session preferences checker.
+        * @param address serves as constraint, so that factory is able to
+        * return different checkers for different clients
+        * @return specific session preferences checker
+        */
+       public SessionPreferencesChecker getPreferencesChecker(final InetSocketAddress address);
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SessionProposal.java b/framework/src/main/java/org/opendaylight/protocol/framework/SessionProposal.java
new file mode 100644 (file)
index 0000000..2e94d58
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+/**
+ * Interface that provides the initial acceptable session characteristics
+ * with which the session should be started. This interface should be
+ * implemented by a protocol specific abstract class, that is extended by
+ * a final class that implements the methods.
+ */
+public interface SessionProposal {
+
+       /**
+        * Returns specific Session Preferences object for this IP address.
+        * @return SessionPreferences DTO with acceptable session characteristics
+        */
+       public SessionPreferences getProposal();
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SessionProposalFactory.java b/framework/src/main/java/org/opendaylight/protocol/framework/SessionProposalFactory.java
new file mode 100644 (file)
index 0000000..8498c90
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.net.InetSocketAddress;
+
+/**
+ * Factory for generating Session proposals. Used by a server. Interface needs to be implemented
+ * by a protocol specific abstract class that will produce protocol specific Session Proposals.
+ * The abstract class should be extended by the user in order to return particular object.
+ *
+ * Example:
+ *
+ * public abstract class PCEPSessionProposalFactory implements SessionProposalFactory { ... }
+ *
+ * public final class SimplePCEPSessionProposalFactory extends PCEPSessionProposalFactory { ... }
+ */
+public interface SessionProposalFactory {
+
+       /**
+        * Returns session proposal.
+        *
+        * @param address
+        *            serves as constraint, so that factory is able to return
+        *            different proposals for different addresses
+        * @param sessionId
+        *            identifier of the session
+        * @return specific session proposal
+        */
+       public SessionProposal getSessionProposal(final InetSocketAddress address, final int sessionId);
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/SessionStreams.java b/framework/src/main/java/org/opendaylight/protocol/framework/SessionStreams.java
new file mode 100644 (file)
index 0000000..bb1fd16
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.TimerTask;
+
+/**
+ * DTO object to be attached to socket channel. Contains session and
+ * streams associated with the socket channel.
+ */
+final class SessionStreams {
+
+       private final ProtocolInputStream inputStream;
+
+       private final PipedInputStream pipedInputStream;
+
+       private final PipedOutputStream pipedOutputStream;
+
+       private final ProtocolSession session;
+
+       final ProtocolConnection connection;
+       int connectCount = 0;
+       TimerTask timer = null;
+
+       SessionStreams(PipedOutputStream pipedOutputStream,
+                       PipedInputStream pipedInputStream,
+                       ProtocolInputStream inputStream,
+                       ProtocolSession session, ProtocolConnection connection) {
+               this.pipedOutputStream = pipedOutputStream;
+               this.pipedInputStream = pipedInputStream;
+               this.inputStream = inputStream;
+               this.session = session;
+               this.connection = connection;
+       }
+
+       PipedOutputStream getPipedOutputStream() {
+               return this.pipedOutputStream;
+       }
+
+       PipedInputStream getPipedInputStream() {
+               return this.pipedInputStream;
+       }
+
+       ProtocolInputStream getProtocolInputStream() {
+               return this.inputStream;
+       }
+
+       ProtocolSession getSession() {
+               return this.session;
+       }
+}
diff --git a/framework/src/main/java/org/opendaylight/protocol/framework/TerminationReason.java b/framework/src/main/java/org/opendaylight/protocol/framework/TerminationReason.java
new file mode 100644 (file)
index 0000000..9f7af56
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+/**
+ * Marker interface for grouping session termination cause.
+ */
+public interface TerminationReason {
+
+       /**
+        * Get cause of session termination.
+        * @return human-readable cause.
+        */
+       public String getErrorMessage();
+}
+
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/ComplementaryTest.java b/framework/src/test/java/org/opendaylight/protocol/framework/ComplementaryTest.java
new file mode 100644 (file)
index 0000000..2d6cad8
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class ComplementaryTest {
+
+       private class ProtocolMessageImpl implements ProtocolMessage {
+
+               private static final long serialVersionUID = 1L;
+       }
+
+       private class ProtocolMessageFactoryImpl implements ProtocolMessageFactory {
+
+               public ProtocolMessageFactoryImpl() {
+
+               }
+
+               @Override
+               public ProtocolMessage parse(final byte[] bytes,
+                               final ProtocolMessageHeader msgHeader) throws DeserializerException,
+                               DocumentedException {
+                       return null;
+               }
+
+               @Override
+               public byte[] put(final ProtocolMessage msg) {
+                       return new byte[]{ 12, 13 };
+               }
+       }
+
+       @Test
+       public void testExceptions() {
+               final DeserializerException de = new DeserializerException("some error");
+               final DocumentedException ee = new DocumentedException("some error");
+
+               assertEquals(de.getMessage(), ee.getMessage());
+       }
+
+       @Test
+       public void testProtocolOutputStream() {
+               final ProtocolOutputStream pos = new ProtocolOutputStream();
+               pos.putMessage(new ProtocolMessageImpl(), new ProtocolMessageFactoryImpl());
+               try {
+                       pos.putMessage(new ProtocolMessageImpl(), new ProtocolMessageFactory() {
+
+                               @Override
+                               public byte[] put(final ProtocolMessage msg) {
+                                       return null;
+                               }
+
+                               @Override
+                               public ProtocolMessage parse(final byte[] bytes, final ProtocolMessageHeader msgHeader)
+                                               throws DeserializerException, DocumentedException {
+                                       return null;
+                               }
+                       });
+                       fail("Exception should have occured.");
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Message parsed to null.", e.getMessage());
+                       assertEquals(1, pos.getBuffers().size());
+                       assertArrayEquals(new byte[] { 12, 13}, pos.getBuffers().peek().array());
+               }
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/Message.java b/framework/src/test/java/org/opendaylight/protocol/framework/Message.java
new file mode 100644 (file)
index 0000000..684d646
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+public class Message implements ProtocolMessage {
+
+       private static final long serialVersionUID = 1L;
+
+       private final String s;
+
+       public Message(final String s) {
+               this.s = s;
+       }
+
+       public String getMessage() {
+               return s;
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/MessageFactory.java b/framework/src/test/java/org/opendaylight/protocol/framework/MessageFactory.java
new file mode 100644 (file)
index 0000000..593d43c
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.nio.ByteBuffer;
+
+import com.google.common.base.Charsets;
+
+public class MessageFactory implements ProtocolMessageFactory {
+
+       @Override
+       public ProtocolMessage parse(byte[] bytes, ProtocolMessageHeader msgHeader)
+                       throws DeserializerException, DocumentedException {
+               return new Message(Charsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString());
+       }
+
+       @Override
+       public byte[] put(ProtocolMessage msg) {
+               return ((Message)msg).getMessage().getBytes();
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SecureServerTest.java b/framework/src/test/java/org/opendaylight/protocol/framework/SecureServerTest.java
new file mode 100644 (file)
index 0000000..febd21c
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Random;
+import java.util.Timer;
+import java.util.concurrent.Executors;
+
+import javax.net.ssl.SSLContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.util.SSLUtil;
+
+public class SecureServerTest {
+       static final Random rnd = new Random();
+
+       private static final int MAX_MSGSIZE = 500;
+       final SimpleSessionListener pce = new SimpleSessionListener();
+       ProtocolSession session;
+       ProtocolServer server;
+       DispatcherImpl dispatcher;
+       SSLContext context;
+       int port;
+
+       @Before
+       public void setUp() throws Exception {
+               final InputStream keyStore = SecureServerTest.class.getResourceAsStream("/keystore.jks");
+               final InputStream trustStore = SecureServerTest.class.getResourceAsStream("/keystore.jks");
+               this.context = SSLUtil.initializeSecureContext("keystore", keyStore, trustStore, "SunX509");
+               keyStore.close();
+               trustStore.close();
+
+               this.dispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+               this.port = rnd.nextInt(10000) + 20000;
+       }
+
+       @After
+       public void tearDown() throws IOException {
+               this.dispatcher.onSessionClosed(this.session);
+               this.server.close();
+               this.dispatcher.stop();
+               try {
+                       Thread.sleep(100);
+               } catch (final InterruptedException e) {
+                       e.printStackTrace();
+               }
+       }
+
+       @Test
+       public void testServerConnection() throws Exception {
+
+               this.server = this.dispatcher.createServer(new InetSocketAddress("127.0.0.3", this.port), new ProtocolConnectionFactory() {
+                       @Override
+                       public ProtocolConnection createProtocolConnection(final InetSocketAddress address) {
+                               return new ProtocolConnection() {
+                                       @Override
+                                       public SessionPreferencesChecker getProposalChecker() {
+                                               return new SimpleSessionProposalChecker();
+                                       }
+
+                                       @Override
+                                       public SessionPreferences getProposal() {
+                                               return new SimpleSessionPreferences();
+                                       }
+
+                                       @Override
+                                       public InetSocketAddress getPeerAddress() {
+                                               return address;
+                                       }
+
+                                       @Override
+                                       public SessionListener getListener() {
+                                               return new SimpleSessionListener();
+                                       }
+                               };
+                       }
+               }, new SimpleSessionFactory(MAX_MSGSIZE), SimpleInputStream.FACTORY, this.context);
+
+               try {
+                       this.server = this.dispatcher.createServer(new InetSocketAddress("127.0.0.3", this.port), null, null, null, null);
+                       fail("Exception should have occured.");
+               } catch (final IllegalStateException e) {
+                       assertTrue(e.getMessage().startsWith("Server with this address:") && e.getMessage().endsWith("was already created."));
+               }
+
+               this.session = this.dispatcher.createClient(new ProtocolConnection() {
+                       @Override
+                       public SessionPreferencesChecker getProposalChecker() {
+                               return new SimpleSessionProposalChecker();
+                       }
+
+                       @Override
+                       public SessionPreferences getProposal() {
+                               return new SimpleSessionPreferences();
+                       }
+
+                       @Override
+                       public InetSocketAddress getPeerAddress() {
+                               return new InetSocketAddress("127.0.0.3", SecureServerTest.this.port);
+                       }
+
+                       @Override
+                       public SessionListener getListener() {
+                               return SecureServerTest.this.pce;
+                       }
+               }, new SimpleSessionFactory(MAX_MSGSIZE), SimpleInputStream.FACTORY, this.context);
+
+               try {
+                       this.session = this.dispatcher.createClient(new ProtocolConnection() {
+                               @Override
+                               public SessionPreferencesChecker getProposalChecker() {
+                                       return new SimpleSessionProposalChecker();
+                               }
+
+                               @Override
+                               public SessionPreferences getProposal() {
+                                       return new SimpleSessionPreferences();
+                               }
+
+                               @Override
+                               public InetSocketAddress getPeerAddress() {
+                                       return new InetSocketAddress("127.0.0.3", SecureServerTest.this.port);
+                               }
+
+                               @Override
+                               public SessionListener getListener() {
+                                       return SecureServerTest.this.pce;
+                               }
+                       }, null, null, null);
+                       fail("Exception should have occured.");
+               } catch (final IllegalStateException e) {
+                       assertTrue(e.getMessage().startsWith("Attempt to create duplicate client session to the same address:"));
+               }
+
+               synchronized (this.pce) {
+                       while (!this.pce.up)
+                               this.pce.wait();
+               }
+       }
+
+       @Test
+       public void testIO() throws IOException, InterruptedException, KeyManagementException, UnrecoverableKeyException,
+                       NoSuchAlgorithmException, KeyStoreException, CertificateException {
+               this.server = this.dispatcher.createServer(new InetSocketAddress("127.0.0.3", this.port), new ProtocolConnectionFactory() {
+                       @Override
+                       public ProtocolConnection createProtocolConnection(final InetSocketAddress address) {
+                               return new ProtocolConnection() {
+
+                                       @Override
+                                       public SessionPreferencesChecker getProposalChecker() {
+                                               return new SimpleSessionProposalChecker();
+                                       }
+
+                                       @Override
+                                       public SessionPreferences getProposal() {
+                                               return new SimpleSessionPreferences();
+                                       }
+
+                                       @Override
+                                       public InetSocketAddress getPeerAddress() {
+                                               return address;
+                                       }
+
+                                       @Override
+                                       public SessionListener getListener() {
+                                               return new SimpleSessionListener();
+                                       }
+                               };
+                       }
+               }, new ProtocolSessionFactory() {
+                       @Override
+                       public ProtocolSession getProtocolSession(final SessionParent parent, final Timer timer, final ProtocolConnection connection,
+                                       final int sessionId) {
+                               return new Session(parent, MAX_MSGSIZE);
+                       }
+               }, SimpleInputStream.FACTORY, this.context);
+
+               this.session = this.dispatcher.createClient(new ProtocolConnection() {
+                       @Override
+                       public SessionPreferencesChecker getProposalChecker() {
+                               return new SimpleSessionProposalChecker();
+                       }
+
+                       @Override
+                       public SessionPreferences getProposal() {
+                               return new SimpleSessionPreferences();
+                       }
+
+                       @Override
+                       public InetSocketAddress getPeerAddress() {
+                               return new InetSocketAddress("127.0.0.3", SecureServerTest.this.port);
+                       }
+
+                       @Override
+                       public SessionListener getListener() {
+                               return new SimpleSessionListener();
+                       }
+               }, new ProtocolSessionFactory() {
+                       @Override
+                       public ProtocolSession getProtocolSession(final SessionParent parent, final Timer timer, final ProtocolConnection connection,
+                                       final int sessionId) {
+                               return new Session(parent, MAX_MSGSIZE);
+                       }
+               }, SimpleInputStream.FACTORY, this.context);
+       }
+
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/ServerTest.java b/framework/src/test/java/org/opendaylight/protocol/framework/ServerTest.java
new file mode 100644 (file)
index 0000000..4780e9c
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+import org.junit.After;
+import org.junit.Test;
+
+public class ServerTest {
+       private static final int MAX_MSGSIZE = 500;
+       public static final int PORT = 18080;
+
+       DispatcherImpl clientDispatcher, dispatcher;
+
+       final SimpleSessionListener pce = new SimpleSessionListener();
+
+       ProtocolSession session = null;
+
+       ProtocolServer server = null;
+
+       @Test
+       public void testConnectionEstablished() throws Exception {
+               this.dispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+
+               this.server = this.dispatcher.createServer(new InetSocketAddress("127.0.0.3", PORT), new ProtocolConnectionFactory() {
+                       @Override
+                       public ProtocolConnection createProtocolConnection(final InetSocketAddress address) {
+
+                               return new ProtocolConnection() {
+                                       @Override
+                                       public SessionPreferencesChecker getProposalChecker() {
+                                               return new SimpleSessionProposalChecker();
+                                       }
+
+                                       @Override
+                                       public SessionPreferences getProposal() {
+                                               return new SimpleSessionPreferences();
+                                       }
+
+                                       @Override
+                                       public InetSocketAddress getPeerAddress() {
+                                               return address;
+                                       }
+
+                                       @Override
+                                       public SessionListener getListener() {
+                                               return new SimpleSessionListener();
+                                       }
+                               };
+                       }
+               }, new SimpleSessionFactory(MAX_MSGSIZE), SimpleInputStream.FACTORY);
+
+               try {
+                       this.server = this.dispatcher.createServer(new InetSocketAddress("127.0.0.3", PORT), null, null, null);
+                       fail("Exception should have occured.");
+               } catch (final IllegalStateException e) {
+                       assertTrue(e.getMessage().startsWith("Server with this address:") && e.getMessage().endsWith("was already created."));
+               }
+               
+               this.clientDispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+
+               this.session = this.clientDispatcher.createClient(new ProtocolConnection() {
+                       @Override
+                       public SessionPreferencesChecker getProposalChecker() {
+                               return new SimpleSessionProposalChecker();
+                       }
+
+                       @Override
+                       public SessionPreferences getProposal() {
+                               return new SimpleSessionPreferences();
+                       }
+
+                       @Override
+                       public InetSocketAddress getPeerAddress() {
+                               return new InetSocketAddress("127.0.0.3", PORT);
+                       }
+
+                       @Override
+                       public SessionListener getListener() {
+                               return ServerTest.this.pce;
+                       }
+               }, new SimpleSessionFactory(MAX_MSGSIZE), SimpleInputStream.FACTORY);
+
+               final int maxAttempts = 1000;
+               int attempts = 0;
+               synchronized (this.pce) {
+                       while (!this.pce.up && ++attempts < maxAttempts) {
+                               this.pce.wait(100);
+                       }
+               }
+               assertTrue(this.pce.up);
+       }
+
+       @Test
+       public void testConnectionFailed() throws IOException, InterruptedException {
+               this.dispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+               this.clientDispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+
+               this.session = this.clientDispatcher.createClient(new ProtocolConnection() {
+                       @Override
+                       public SessionPreferencesChecker getProposalChecker() {
+                               return new SimpleSessionProposalChecker();
+                       }
+
+                       @Override
+                       public SessionPreferences getProposal() {
+                               return new SimpleSessionPreferences();
+                       }
+
+                       @Override
+                       public InetSocketAddress getPeerAddress() {
+                               return new InetSocketAddress("127.0.0.3", PORT);
+                       }
+
+                       @Override
+                       public SessionListener getListener() {
+                               return ServerTest.this.pce;
+                       }
+               }, new SimpleSessionFactory(MAX_MSGSIZE), SimpleInputStream.FACTORY);
+               final int maxAttempts = 1000;
+               int attempts = 0;
+               synchronized (this.pce) {
+                       while (!this.pce.failed && ++attempts < maxAttempts) {
+                               this.pce.wait(100);
+                       }
+               }
+               assertTrue(this.pce.failed);
+       }
+
+       @After
+       public void tearDown() throws IOException {
+               this.dispatcher.onSessionClosed(this.session);
+               if (this.server != null)
+                       this.server.close();
+               this.dispatcher.stop();
+               this.clientDispatcher.stop();
+               try {
+                       Thread.sleep(100);
+               } catch (final InterruptedException e) {
+                       throw new RuntimeException(e);
+               }
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/Session.java b/framework/src/test/java/org/opendaylight/protocol/framework/Session.java
new file mode 100644 (file)
index 0000000..0591f0e
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+public class Session implements ProtocolSession {
+
+       private static final Logger logger = LoggerFactory.getLogger(Session.class);
+
+       private final ProtocolOutputStream pos;
+
+       public final List<ProtocolMessage> msgs = Lists.newArrayList();
+
+       private final ProtocolMessageFactory pmf = new MessageFactory();
+
+       private final SessionParent parent;
+
+       public boolean up = false;
+
+       private final int maxMsgSize;
+
+       public Session(final SessionParent parent, final int maxMsgSize) {
+               this.pos = new ProtocolOutputStream();
+               this.parent = parent;
+               this.maxMsgSize = maxMsgSize;
+       }
+
+       @Override
+       public void close() throws IOException {
+
+       }
+
+       @Override
+       public void startSession() {
+               this.pos.putMessage(new Message("hello"), this.pmf);
+               this.parent.checkOutputBuffer(this);
+       }
+
+       @Override
+       public ProtocolOutputStream getStream() {
+               return this.pos;
+       }
+
+       @Override
+       public void handleMessage(ProtocolMessage msg) {
+               logger.debug("Message received: {}", ((Message)msg).getMessage());
+               this.up = true;
+               this.msgs.add(msg);
+               logger.debug(this.msgs.size() + "");
+       }
+
+       @Override
+       public void handleMalformedMessage(DeserializerException e) {
+               logger.debug("Malformed message: {}", e.getMessage(), e);
+       }
+
+       @Override
+       public void handleMalformedMessage(DocumentedException e) {
+               logger.debug("Malformed message: {}", e.getMessage(), e);
+       }
+
+       @Override
+       public void endOfInput() {
+               logger.debug("End of input reported.");
+       }
+
+       @Override
+       public ProtocolMessageFactory getMessageFactory() {
+               return null;
+       }
+
+       @Override
+       public void onConnectionFailed(IOException e) {
+               logger.debug("Connection failed: {}", e.getMessage(), e);
+       }
+
+       @Override
+       public int maximumMessageSize() {
+               return maxMsgSize;
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleInputStream.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleInputStream.java
new file mode 100644 (file)
index 0000000..e06ea49
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+
+public class SimpleInputStream implements ProtocolInputStream {
+       public static final ProtocolInputStreamFactory FACTORY = new ProtocolInputStreamFactory() {
+               @Override
+               public ProtocolInputStream getProtocolInputStream(final PipedInputStream pis, final ProtocolMessageFactory pmf) {
+                       return new SimpleInputStream();
+               }
+       };
+
+       private SimpleInputStream() {
+       }
+
+       @Override
+       public boolean isMessageAvailable() throws IOException {
+               return true;
+       }
+
+       @Override
+       public ProtocolMessage getMessage() throws DeserializerException, IOException, DocumentedException {
+               return null;
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleMessageFactory.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleMessageFactory.java
new file mode 100644 (file)
index 0000000..d25f566
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+public class SimpleMessageFactory implements ProtocolMessageFactory {
+
+       @Override
+       public ProtocolMessage parse(byte[] bytes, ProtocolMessageHeader msgHeader)
+                       throws DeserializerException, DocumentedException {
+               return null;
+       }
+
+       @Override
+       public byte[] put(ProtocolMessage msg) {
+               return null;
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSession.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSession.java
new file mode 100644 (file)
index 0000000..49fb5de
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+
+public final class SimpleSession implements ProtocolSession {
+
+       private final SessionListener listener;
+
+       private final SessionParent d;
+
+       private final int maxMsgSize;
+
+       public SimpleSession(ProtocolConnection connection, SessionParent d, int maxMsgSize) {
+               this.listener = connection.getListener();
+               this.d = d;
+               this.maxMsgSize = maxMsgSize;
+       }
+
+       @Override
+       public void close() throws IOException {
+               this.d.onSessionClosed(this);
+       }
+
+       @Override
+       public void startSession() {
+               ((SimpleSessionListener)this.listener).onSessionUp(this, null, null);
+       }
+
+       @Override
+       public ProtocolOutputStream getStream() {
+               return null;
+       }
+
+       @Override
+       public void handleMessage(ProtocolMessage msg) {
+       }
+
+       @Override
+       public void handleMalformedMessage(DeserializerException e) {
+       }
+
+       @Override
+       public void handleMalformedMessage(DocumentedException e) {
+       }
+
+       @Override
+       public void endOfInput() {
+       }
+
+       @Override
+       public ProtocolMessageFactory getMessageFactory() {
+               return null;
+       }
+
+       @Override
+       public void onConnectionFailed(IOException e) {
+               ((SimpleSessionListener)this.listener).onConnectionFailed(this, e);
+       }
+
+       @Override
+       public int maximumMessageSize() {
+               return maxMsgSize;
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionFactory.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionFactory.java
new file mode 100644 (file)
index 0000000..f982677
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.util.Timer;
+
+public final class SimpleSessionFactory implements ProtocolSessionFactory {
+       private final int maximumMessageSize;
+
+       public SimpleSessionFactory(int maximumMessageSize) {
+               this.maximumMessageSize = maximumMessageSize;
+       }
+
+       @Override
+       public ProtocolSession getProtocolSession(SessionParent parent, Timer timer, ProtocolConnection connection, int sessionId) {
+               return new SimpleSession(connection, parent, maximumMessageSize);
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionListener.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionListener.java
new file mode 100644 (file)
index 0000000..e99ec2d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Simple Session Listener that is notified about messages and changes in the session.
+ */
+public class SimpleSessionListener implements SessionListener {
+       private static final Logger logger = LoggerFactory.getLogger(SimpleSessionListener.class);
+
+       public List<ProtocolMessage> messages = new ArrayList<ProtocolMessage>();
+
+       public boolean up = false;
+
+       public boolean failed = false;
+
+       public void onMessage(ProtocolSession session, ProtocolMessage message) {
+               logger.debug("Received message: " + message.getClass() + " " + message);
+               this.messages.add(message);
+       }
+
+       public synchronized void onSessionUp(ProtocolSession session, SimpleSessionPreferences local,
+                       SimpleSessionPreferences remote) {
+               logger.debug("Session up.");
+               this.up = true;
+               this.notifyAll();
+       }
+
+       public synchronized void onConnectionFailed(ProtocolSession session, Exception e) {
+               logger.debug("Connection Failed: {}", e.getMessage(), e);
+               this.failed = true;
+               this.notifyAll();
+               try {
+                       session.close();
+               } catch (final IOException ex) {
+                       logger.warn("Session could not be closed.");
+               }
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionListenerFactory.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionListenerFactory.java
new file mode 100644 (file)
index 0000000..eb722ce
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.net.InetAddress;
+
+public class SimpleSessionListenerFactory implements SessionListenerFactory {
+
+       @Override
+       public SimpleSessionListener getSessionListener(InetAddress address) {
+               return new SimpleSessionListener();
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionPreferences.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionPreferences.java
new file mode 100644 (file)
index 0000000..880a014
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+public class SimpleSessionPreferences implements SessionPreferences {
+
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposal.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposal.java
new file mode 100644 (file)
index 0000000..6246582
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+public class SimpleSessionProposal implements SessionProposal {
+       @Override
+       public SessionPreferences getProposal() {
+               return new SimpleSessionPreferences();
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposalChecker.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposalChecker.java
new file mode 100644 (file)
index 0000000..47e2097
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+public class SimpleSessionProposalChecker implements SessionPreferencesChecker {
+
+       @Override
+       public Boolean checkSessionCharacteristics(SessionPreferences openObj) {
+               return true;
+       }
+
+       @Override
+       public SessionPreferences getNewProposal(SessionPreferences open) {
+               return new SimpleSessionPreferences();
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposalCheckerFactory.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposalCheckerFactory.java
new file mode 100644 (file)
index 0000000..ca7f21c
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.net.InetSocketAddress;
+
+public class SimpleSessionProposalCheckerFactory implements
+               SessionPreferencesCheckerFactory {
+
+       @Override
+       public SessionPreferencesChecker getPreferencesChecker(
+                       InetSocketAddress address) {
+               return new SimpleSessionProposalChecker();
+       }
+}
diff --git a/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposalFactory.java b/framework/src/test/java/org/opendaylight/protocol/framework/SimpleSessionProposalFactory.java
new file mode 100644 (file)
index 0000000..429e554
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.framework;
+
+import java.net.InetSocketAddress;
+
+public class SimpleSessionProposalFactory implements SessionProposalFactory {
+
+       @Override
+       public SessionProposal getSessionProposal(InetSocketAddress address, int sessionId) {
+               return new SimpleSessionProposal();
+       }
+}
diff --git a/framework/src/test/resources/keystore.jks b/framework/src/test/resources/keystore.jks
new file mode 100644 (file)
index 0000000..e315823
Binary files /dev/null and b/framework/src/test/resources/keystore.jks differ
diff --git a/framework/src/test/resources/logback-test.xml b/framework/src/test/resources/logback-test.xml
new file mode 100644 (file)
index 0000000..2838411
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+    </encoder>
+  </appender>
+
+  <root level="DEBUG">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
diff --git a/mockito-configuration/.gitignore b/mockito-configuration/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/mockito-configuration/.project b/mockito-configuration/.project
new file mode 100644 (file)
index 0000000..f1f4069
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>mockito-configuration</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/mockito-configuration/bin/.gitignore b/mockito-configuration/bin/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/mockito-configuration/bin/.project b/mockito-configuration/bin/.project
new file mode 100644 (file)
index 0000000..f1f4069
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>mockito-configuration</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/mockito-configuration/bin/pom.xml b/mockito-configuration/bin/pom.xml
new file mode 100644 (file)
index 0000000..f8e6fb4
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>protocol-parent</artifactId>
+               <version>0.1</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>mockito-configuration</artifactId>
+       <description>Default mockito configuration</description>
+       <packaging>jar</packaging> <!-- not needed in OSGi -->
+    <name>${project.artifactId}</name>
+    <version>1.0</version>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <!-- all those dependencies will be in test scope as mockito-configuration should be referenced as test scope dependency -->
+               <dependency>
+                       <groupId>org.mockito</groupId>
+                       <artifactId>mockito-core</artifactId>
+                       <version>1.9.5</version>
+               </dependency>
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <version>${junit.version}</version>
+               </dependency>
+       </dependencies>
+
+       <distributionManagement>
+               <site>
+                       <id>mockito-configuration</id>
+                       <name>MOCKITO-CONFIGURATION Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+</project>
diff --git a/mockito-configuration/bin/src/main/java/org/mockito/configuration/ArgumentsExtractorVerifier.class b/mockito-configuration/bin/src/main/java/org/mockito/configuration/ArgumentsExtractorVerifier.class
new file mode 100644 (file)
index 0000000..a712ad0
Binary files /dev/null and b/mockito-configuration/bin/src/main/java/org/mockito/configuration/ArgumentsExtractorVerifier.class differ
diff --git a/mockito-configuration/bin/src/main/java/org/mockito/configuration/MockitoConfiguration.class b/mockito-configuration/bin/src/main/java/org/mockito/configuration/MockitoConfiguration.class
new file mode 100644 (file)
index 0000000..bcb14d1
Binary files /dev/null and b/mockito-configuration/bin/src/main/java/org/mockito/configuration/MockitoConfiguration.class differ
diff --git a/mockito-configuration/bin/src/main/java/org/mockito/configuration/ThrowsUnstubbedMethodException.class b/mockito-configuration/bin/src/main/java/org/mockito/configuration/ThrowsUnstubbedMethodException.class
new file mode 100644 (file)
index 0000000..9274a2a
Binary files /dev/null and b/mockito-configuration/bin/src/main/java/org/mockito/configuration/ThrowsUnstubbedMethodException.class differ
diff --git a/mockito-configuration/bin/src/main/java/org/mockito/configuration/UnstubbedMethodException.class b/mockito-configuration/bin/src/main/java/org/mockito/configuration/UnstubbedMethodException.class
new file mode 100644 (file)
index 0000000..12ea0cd
Binary files /dev/null and b/mockito-configuration/bin/src/main/java/org/mockito/configuration/UnstubbedMethodException.class differ
diff --git a/mockito-configuration/bin/src/main/resources/logback-test.xml b/mockito-configuration/bin/src/main/resources/logback-test.xml
new file mode 100644 (file)
index 0000000..2838411
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+    </encoder>
+  </appender>
+
+  <root level="DEBUG">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
diff --git a/mockito-configuration/bin/src/test/java/org/mockito/configuration/ArgumentsExtractorVerifierTest.class b/mockito-configuration/bin/src/test/java/org/mockito/configuration/ArgumentsExtractorVerifierTest.class
new file mode 100644 (file)
index 0000000..0ac3965
Binary files /dev/null and b/mockito-configuration/bin/src/test/java/org/mockito/configuration/ArgumentsExtractorVerifierTest.class differ
diff --git a/mockito-configuration/bin/src/test/java/org/mockito/configuration/DefaultAnswerTest.class b/mockito-configuration/bin/src/test/java/org/mockito/configuration/DefaultAnswerTest.class
new file mode 100644 (file)
index 0000000..f7215ec
Binary files /dev/null and b/mockito-configuration/bin/src/test/java/org/mockito/configuration/DefaultAnswerTest.class differ
diff --git a/mockito-configuration/pom.xml b/mockito-configuration/pom.xml
new file mode 100644 (file)
index 0000000..f8e6fb4
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>protocol-parent</artifactId>
+               <version>0.1</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>mockito-configuration</artifactId>
+       <description>Default mockito configuration</description>
+       <packaging>jar</packaging> <!-- not needed in OSGi -->
+    <name>${project.artifactId}</name>
+    <version>1.0</version>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <!-- all those dependencies will be in test scope as mockito-configuration should be referenced as test scope dependency -->
+               <dependency>
+                       <groupId>org.mockito</groupId>
+                       <artifactId>mockito-core</artifactId>
+                       <version>1.9.5</version>
+               </dependency>
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <version>${junit.version}</version>
+               </dependency>
+       </dependencies>
+
+       <distributionManagement>
+               <site>
+                       <id>mockito-configuration</id>
+                       <name>MOCKITO-CONFIGURATION Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+</project>
diff --git a/mockito-configuration/src/main/java/org/mockito/configuration/ArgumentsExtractorVerifier.java b/mockito-configuration/src/main/java/org/mockito/configuration/ArgumentsExtractorVerifier.java
new file mode 100644 (file)
index 0000000..53db342
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.mockito.configuration;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+import java.util.List;
+
+/**
+ * Verifier that extracts arguments from actual invocation. Useful when deeper validation of arguments is needed.
+ *
+ */
+public class ArgumentsExtractorVerifier implements VerificationMode {
+               private Object[] arguments;
+
+               @Override
+               public void verify(VerificationData data) {
+                       InvocationsFinder finder = new InvocationsFinder();
+                       List<Invocation> actualInvocations = finder.findInvocations(data.getAllInvocations(), data.getWanted());
+                       if (actualInvocations.size() != 1) {
+                               throw new MockitoException("This verifier can only be used with 1 invocation, got " + actualInvocations.size());
+                       }
+                       Invocation invocation = actualInvocations.get(0);
+                       arguments = invocation.getArguments();
+                       invocation.markVerified();
+
+               }
+               public Object[] getArguments(){
+                       return arguments;
+               }
+       }
diff --git a/mockito-configuration/src/main/java/org/mockito/configuration/MockitoConfiguration.java b/mockito-configuration/src/main/java/org/mockito/configuration/MockitoConfiguration.java
new file mode 100644 (file)
index 0000000..22d3a1e
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.mockito.configuration;
+
+import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Configuration customization for Mockito. Change default answer from {@link ReturnsEmptyValues}
+ * to {@link ThrowsUnstubbedMethodException}.
+ */
+public class MockitoConfiguration extends DefaultMockitoConfiguration {
+
+       @Override
+       public Answer<Object> getDefaultAnswer() {
+               return new ThrowsUnstubbedMethodException();
+       }
+}
diff --git a/mockito-configuration/src/main/java/org/mockito/configuration/ThrowsUnstubbedMethodException.java b/mockito-configuration/src/main/java/org/mockito/configuration/ThrowsUnstubbedMethodException.java
new file mode 100644 (file)
index 0000000..83262bc
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.mockito.configuration;
+
+import java.io.Serializable;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Answer that throws {@link UnstubbedMethodException}.
+ */
+public class ThrowsUnstubbedMethodException implements Answer<Object>, Serializable {
+       private static final long serialVersionUID = 1L;
+
+    public ThrowsUnstubbedMethodException() {
+    }
+
+    @Override
+       public Object answer(InvocationOnMock invocation) throws Throwable {
+        Throwable t = new UnstubbedMethodException(invocation.toString() + " was not stubbed");
+        throw t;
+    }
+}
diff --git a/mockito-configuration/src/main/java/org/mockito/configuration/UnstubbedMethodException.java b/mockito-configuration/src/main/java/org/mockito/configuration/UnstubbedMethodException.java
new file mode 100644 (file)
index 0000000..ac74866
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.mockito.configuration;
+
+
+/**
+ * Exception to be thrown on unstubbed method call.
+ */
+public class UnstubbedMethodException extends RuntimeException {
+
+       private static final long serialVersionUID = 1L;
+
+       public UnstubbedMethodException(String message) {
+               super(message);
+       }
+
+}
diff --git a/mockito-configuration/src/main/resources/logback-test.xml b/mockito-configuration/src/main/resources/logback-test.xml
new file mode 100644 (file)
index 0000000..2838411
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+    </encoder>
+  </appender>
+
+  <root level="DEBUG">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
diff --git a/mockito-configuration/src/test/java/org/mockito/configuration/ArgumentsExtractorVerifierTest.java b/mockito-configuration/src/test/java/org/mockito/configuration/ArgumentsExtractorVerifierTest.java
new file mode 100644 (file)
index 0000000..ba3a41b
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.mockito.configuration;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class ArgumentsExtractorVerifierTest {
+
+       @Mock
+       List<String> mockedList;
+
+       @Test
+       public void test() {
+               MockitoAnnotations.initMocks(this);
+               doReturn(true).when(this.mockedList).add(any(String.class));
+               final String argument = "something";
+               this.mockedList.add(argument);
+               // retrieve argument
+               final ArgumentsExtractorVerifier argumentsExtractorVerifier = new ArgumentsExtractorVerifier();
+               verify(this.mockedList, argumentsExtractorVerifier).add(any(String.class));
+               assertArrayEquals(new Object[] { argument }, argumentsExtractorVerifier.getArguments());
+       }
+
+}
diff --git a/mockito-configuration/src/test/java/org/mockito/configuration/DefaultAnswerTest.java b/mockito-configuration/src/test/java/org/mockito/configuration/DefaultAnswerTest.java
new file mode 100644 (file)
index 0000000..c2019ed
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.mockito.configuration;
+
+import static org.junit.Assert.*;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class DefaultAnswerTest {
+
+       @Test
+       public void testAnswering() throws IOException {
+               Closeable mock = Mockito.mock(Closeable.class);
+               try {
+                       mock.close();
+                       fail();
+               } catch (UnstubbedMethodException e) {
+                       assertEquals("closeable.close(); was not stubbed", e.getMessage());
+               }
+       }
+
+
+
+}
diff --git a/pcep/.gitignore b/pcep/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/pcep/.project b/pcep/.project
new file mode 100644 (file)
index 0000000..bf54a41
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>pcep-subsystem</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/pcep/api/.gitignore b/pcep/api/.gitignore
new file mode 100644 (file)
index 0000000..6cff1d5
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.settings
+.classpath
diff --git a/pcep/api/.project b/pcep/api/.project
new file mode 100644 (file)
index 0000000..cb644bc
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>pcep-api</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/pcep/api/pom.xml b/pcep/api/pom.xml
new file mode 100644 (file)
index 0000000..4e2ba72
--- /dev/null
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>pcep-parent</artifactId>
+               <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>pcep-api</artifactId>
+       <description>PCE Protocol API</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>framework</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-api</artifactId>
+                       <version>${slf4j.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>mockito-configuration</artifactId>
+                       <version>1.0</version>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.pcep,
+                                                       org.opendaylight.protocol.pcep.concepts,
+                                                       org.opendaylight.protocol.pcep.message,
+                                                       org.opendaylight.protocol.pcep.object,
+                                                       org.opendaylight.protocol.pcep.subobject,
+                                                       org.opendaylight.protocol.pcep.tlv,
+                                               </Export-Package>
+                                               <Import-Package>
+                                                       org.opendaylight.protocol.concepts,
+                            org.opendaylight.protocol.framework,
+                            org.opendaylight.protocol.util,
+                                                       com.google.common.*,
+                                                       javax.management,
+                                                       org.slf4j.*
+                                               </Import-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>${checkstyle.version}</version>
+                               <configuration>
+                                       <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+                                       <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>PCEP-API Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPCloseTermination.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPCloseTermination.java
new file mode 100644 (file)
index 0000000..f8fbbe3
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+
+/**
+ * Used as a reason when one of the regular reasons was the cause of the
+ * termination of a session.
+ */
+public final class PCEPCloseTermination implements TerminationReason {
+
+       private final Reason reason;
+
+       /**
+        * Creates new Termination.
+        * @param reason reason for termination
+        */
+       public PCEPCloseTermination(Reason reason) {
+               this.reason = reason;
+       }
+
+       /* (non-Javadoc)
+        * @see org.opendaylight.protocol.pcep.PCEPTerminationReason#getErrorMessage()
+        */
+       @Override
+       public String getErrorMessage() {
+               return this.reason.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPConnection.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPConnection.java
new file mode 100644 (file)
index 0000000..4310370
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import org.opendaylight.protocol.framework.ProtocolConnection;
+
+public interface PCEPConnection extends ProtocolConnection {
+       @Override
+       public PCEPSessionListener getListener();
+
+       @Override
+       public PCEPSessionPreferences getProposal();
+
+       @Override
+       public PCEPSessionProposalChecker getProposalChecker();
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPConnectionFactory.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPConnectionFactory.java
new file mode 100644 (file)
index 0000000..94326f2
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.ProtocolConnectionFactory;
+
+public interface PCEPConnectionFactory extends ProtocolConnectionFactory {
+       @Override
+       public PCEPConnection createProtocolConnection(final InetSocketAddress address);
+
+       public void setProposal(final PCEPSessionProposalFactory proposals, final InetSocketAddress address, final int sessionId);
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPDeserializerException.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPDeserializerException.java
new file mode 100644 (file)
index 0000000..98084bb
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+
+/**
+ * Used when something occurs during parsing bytes to java objects.
+ */
+public class PCEPDeserializerException extends DeserializerException {
+
+       private static final long serialVersionUID = -7511681435692278498L;
+
+       private static final Logger logger = LoggerFactory.getLogger(PCEPDeserializerException.class);
+
+       private final String message;
+
+       /**
+        * Used when no exact error (from rfc or from draft) is specified.
+        *
+        * @param err
+        *            error message describing the error that occurred
+        */
+       public PCEPDeserializerException(String err) {
+               this(null, err);
+       }
+
+       /**
+        * Used when we want to pass also the exception that occurred.
+        *
+        * @param e
+        *            specific exception that occurred
+        * @param err
+        *            error message describing the error that occurred
+        */
+       public PCEPDeserializerException(Exception e, String err) {
+               super(err, e);
+               this.message = err;
+               logger.error("", this);
+       }
+
+       /**
+        * Returns error message.
+        *
+        * @return error message
+        */
+       public String getErrorMessage() {
+               return this.message;
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPDispatcher.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPDispatcher.java
new file mode 100644 (file)
index 0000000..ff1f1ec
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.ProtocolServer;
+
+/**
+ * Dispatcher class for creating servers and clients.
+ */
+public interface PCEPDispatcher {
+
+       /**
+        * Creates server. Each server needs three factories to pass their instances to client sessions.
+        * @param address to be bound with the server
+        * @param listenerFactory to create listeners for clients
+        * @param proposalFactory to create proposed open objects for clients
+        * @param checkerFactory to create session characteristics checker for clients
+        * @return instance of PCEPServer
+        * @throws IOException if some IO error occurred
+        */
+       public ProtocolServer createServer(final InetSocketAddress address, final PCEPConnectionFactory connectionFactory) throws IOException;
+
+       /**
+        * Creates a client. Needs to be started via the start method.
+        * @param address of the server, where the client will connect
+        * @param sessionListener listener to this session who will be notified about incoming messages and other session events
+        * @param proposal proposes initial Open object
+        * @param checker checks session characteristics and proposes another Open object if necessary
+        * @return session associated with this client.
+        * @throws IOException if some IO error occurred
+        */
+       public PCEPSession createClient(PCEPConnection connection) throws IOException;
+
+       /**
+        * Sets the limit of maximum unknown messages per minute. If not set by the user, default is 5 messages/minute.
+        * @param limit maximum unknown messages per minute
+        */
+       public void setMaxUnknownMessages(final int limit);
+}
+
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPDocumentedException.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPDocumentedException.java
new file mode 100644 (file)
index 0000000..0b58280
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DocumentedException;
+
+/**
+ * There are several errors documented in RFC5440 or in draft, that have
+ * specific meaning for the PCE. This exception is used, when any of those
+ * errors occurs.
+ */
+public class PCEPDocumentedException extends DocumentedException {
+
+       private static final long serialVersionUID = 5146586011100522025L;
+
+       private final PCEPErrors error;
+
+       private static final Logger logger = LoggerFactory.getLogger(PCEPDocumentedException.class);
+
+       /**
+        * Used when an error occured that is described in rfc or draft
+        *
+        * @param message
+        *                      message bound with this exception
+        * @param error
+        *            specific documented error
+        */
+       public PCEPDocumentedException(String message, PCEPErrors error) {
+               super(message);
+               this.error = error;
+               logger.error("Error = " + error, this);
+       }
+
+       /**
+        * Returns specific documented error
+        *
+        * @return documented error
+        */
+       public PCEPErrors getError() {
+               return this.error;
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPErrorTermination.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPErrorTermination.java
new file mode 100644 (file)
index 0000000..a45c961
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+
+/**
+ * Used as a reason when a documented error was the cause of the
+ * termination of a session.
+ */
+public final class PCEPErrorTermination implements TerminationReason {
+
+       private final PCEPErrors error;
+
+       /**
+        * Creates new Termination.
+        * @param error Error that happened.
+        */
+       public PCEPErrorTermination(PCEPErrors error) {
+               this.error = error;
+       }
+
+       /* (non-Javadoc)
+        * @see org.opendaylight.protocol.pcep.PCEPTerminationReason#getErrorMessage()
+        */
+       @Override
+       public String getErrorMessage() {
+               return this.error.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPErrors.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPErrors.java
new file mode 100644 (file)
index 0000000..74f01ae
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+/**
+ * Possible errors listed in RFC5440, RFC 5455 and stateful draft.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-9.12">PCEP-ERROR
+ *      Object(RFC5440)</a>, <a href=
+ *      "http://tools.ietf.org/html/draft-ietf-pce-stateful-pce-01#section-8.4"
+ *      >PCEP-ERROR Object(stateful draft)</a>, <a
+ *      href="http://tools.ietf.org/html/rfc5455#section-3.6">Error Codes for
+ *      CLASSTYPE Object(RFC5455)</a>, <a href=
+ *      "http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt#section-7.1"
+ *      >PCEP-Error Object</a>
+ */
+public enum PCEPErrors {
+       /**
+        * Reception of an invalid Open message or a non Open message.
+        */
+       NON_OR_INVALID_OPEN_MSG,
+       /**
+        * No Open message received before the expiration of the OpenWait timer.
+        */
+       NO_OPEN_BEFORE_EXP_OPENWAIT,
+       /**
+        * Unacceptable and non-negotiable session characteristics.
+        */
+       NON_ACC_NON_NEG_SESSION_CHAR,
+       /**
+        * Unacceptable but negotiable session characteristics.
+        */
+       NON_ACC_NEG_SESSION_CHAR,
+       /**
+        * Reception of a second Open message with still unacceptable session
+        * characteristics.
+        */
+       SECOND_OPEN_MSG,
+       /**
+        * Reception of a PCErr message proposing unacceptable session
+        * characteristics.
+        */
+       PCERR_NON_ACC_SESSION_CHAR,
+       /**
+        * No Keepalive or PCErr message received before the expiration of the
+        * KeepWait timer.
+        */
+       NO_MSG_BEFORE_EXP_KEEPWAIT,
+       /**
+        * Capability not supported.
+        */
+       CAPABILITY_NOT_SUPPORTED,
+       /**
+        * PCEP version not supported.
+        */
+       PCEP_VERSION_NOT_SUPPORTED,
+       /**
+        * Unrecognized object class.
+        */
+       UNRECOGNIZED_OBJ_CLASS,
+       /**
+        * Unrecognized object Type.
+        */
+       UNRECOGNIZED_OBJ_TYPE,
+       /**
+        * Not supported object class.
+        */
+       NOT_SUPPORTED_OBJ_CLASS,
+       /**
+        * Not supported object Type.
+        */
+       NOT_SUPPORTED_OBJ_TYPE,
+       /**
+        * C bit of the METRIC object set (request rejected).
+        */
+       C_BIT_SET,
+       /**
+        * O bit of the RP object cleared (request rejected).
+        */
+       O_BIT_SET,
+       /**
+        * Objective function not allowed (request rejected)
+        */
+       OF_NOT_ALLOWED,
+       /**
+        * OF bit of the RP object set (request rejected)
+        */
+       OF_BIT_SET,
+       /**
+        * Global concurrent optimization not allowed (GCO extension)
+        */
+       GCO_NOT_ALLOWED,
+       /**
+        * P2MP Path computation is not allowed
+        */
+       P2MP_COMPUTATION_NOT_ALLOWED,
+       /**
+        * RP object missing
+        */
+       RP_MISSING,
+       /**
+        * RRO missing for a reoptimization request (R bit of the RP object set).
+        */
+       RRO_MISSING,
+       /**
+        * END-POINTS object missing
+        */
+       END_POINTS_MISSING,
+       /**
+        * LSP cleanup TLV missing
+        */
+       LSP_CLEANUP_TLV_MISSING,
+       /**
+        * SYMBOLIC-PATH-NAME TLV missing
+        */
+       SYMBOLIC_PATH_NAME_MISSING,
+       /**
+        * Synchronized path computation request missing.
+        */
+       SYNC_PATH_COMP_REQ_MISSING,
+       /**
+        * Unknown request reference
+        */
+       UNKNOWN_REQ_REF,
+       /**
+        * Attempt to establish a second PCEP session.
+        */
+       ATTEMPT_2ND_SESSION,
+       /**
+        * LSP Object missing.
+        */
+       LSP_MISSING,
+       /**
+        * ERO Object missing for a path in an LSP Update Request where TE-LSP setup
+        * is requested.
+        */
+       ERO_MISSING,
+       /**
+        * BANDWIDTH Object missing for a path in an LSP Update Request where TE-LSP
+        * setup is requested.
+        */
+       BANDWIDTH_MISSING,
+       /**
+        * LSPA Object missing for a path in an LSP Update Request where TE-LSP
+        * setup is requested.
+        */
+       LSPA_MISSING,
+       /**
+        * LSP-DB-VERSION TLV missing.
+        */
+       DB_VERSION_TLV_MISSING,
+       /**
+        * Reception of an object with P flag not set although the P flag must be
+        * set according to this specification.
+        */
+       P_FLAG_NOT_SET,
+       /**
+        * Insufficient memory (GCO extension)
+        */
+       INSUFFICIENT_MEMORY,
+       /**
+        * Global concurrent optimization not supported (GCO extension)
+        */
+       GCO_NOT_SUPPORTED,
+       /**
+        * Diffserv-aware TE error: Unsupported Class-Type.
+        */
+       UNSUPPORTED_CT,
+       /**
+        * Diffserv-aware TE error: Invalid Class-Type.
+        */
+       INVALID_CT,
+       /**
+        * Diffserv-aware TE error: Class-Type and setup priority do not form a
+        * configured TE-class.
+        */
+       CT_AND_SETUP_PRIORITY_DO_NOT_FORM_TE_CLASS,
+
+       /**
+        * The PCE cannot satisfy the request due to insufficient memory
+        */
+       CANNOT_SATISFY_P2MP_REQUEST_DUE_TO_INSUFFISIENT_MEMMORY,
+       /**
+        * The PCE is not capable of P2MP computation
+        */
+       NOT_CAPPABLE_P2MP_COMPUTATION,
+       /**
+        * The PCE is not capable to satisfy the request due to no END-POINTS with
+        * leaf type 2
+        */
+       P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT2,
+       /**
+        * The PCE is not capable to satisfy the request due to no END-POINTS with
+        * leaf type 3
+        */
+       P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT3,
+       /**
+        * The PCE is not capable to satisfy the request due to no END-POINTS with
+        * leaf type 4
+        */
+       P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT4,
+       /**
+        * The PCE is not capable to satisfy the request due to inconsistent
+        * END-POINTS
+        */
+       P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_INCONSISTENT_EP,
+       /**
+        * P2MP Fragmented request failure
+        */
+       P2MP_FRAGMENTATION_FAILRUE,
+       /**
+        * Attempted LSP Update Request for a non- delegated LSP. The PCEP-ERROR
+        * Object is followed by the LSP Object that identifies the LSP.
+        */
+       UPDATE_REQ_FOR_NON_LSP,
+       /**
+        * Attempted LSP Update Request if active stateful PCE capability was not
+        * negotiated active PCE.
+        */
+       UPDATE_REQ_FOR_NO_STATEFUL,
+       /**
+        * PCE-initiated LSP limit reached.
+        */
+       LSP_LIMIT_REACHED,
+       /**
+        * Delegation for PCE-initiated LSP cannot be revoked
+        */
+       DELEGATION_NOT_REVOKED,
+       /**
+        * A PCE indicates to a PCC that it can not process (an otherwise valid) LSP
+        * State Report. The PCEP-ERROR Object is followed by the LSP Object that
+        * identifies the LSP.
+        */
+       CANNOT_PROCESS_STATE_REPORT,
+       /**
+        * LSP Database version mismatch.
+        */
+       LSP_DB_VERSION_MISMATCH,
+       /**
+        * The LSP-DB-VERSION TLV Missing when State Synchronization Avoidance
+        * enabled.
+        */
+       DB_VERSION_TLV_MISSING_WHEN_SYNC_ALLOWED,
+       /**
+        * SYMBOLIC-PATH-NAME in use
+        */
+       USED_SYMBOLIC_PATH_NAME
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPMessage.java
new file mode 100644 (file)
index 0000000..f11a76c
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import java.util.List;
+
+import org.opendaylight.protocol.framework.ProtocolMessage;
+
+/**
+ * Basic structure for PCEP Message. Cannot be instantiated directly. Current
+ * PCEP version is 1. Each message contains a list of PCEP objects.
+ *
+ */
+public abstract class PCEPMessage implements ProtocolMessage {
+
+       private static final long serialVersionUID = 4293319459468168384L;
+
+       /**
+        * Current supported version of PCEP.
+        */
+       public static final int PCEP_VERSION = 1;
+
+       private final List<PCEPObject> objects;
+
+       /**
+        * Constructor is protected to prevent direct instantiation, but to allow to
+        * call this constructor via super().
+        *
+        * @param objects
+        */
+       protected PCEPMessage(List<PCEPObject> objects) {
+               this.objects = objects;
+       }
+
+       /**
+        * Returns list of all objects that the message contains
+        *
+        * @return list of all objects that the message contains
+        */
+       public List<PCEPObject> getAllObjects() {
+               return this.objects;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.objects == null) ? 0 : this.objects.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPMessage other = (PCEPMessage) obj;
+               if (this.objects == null) {
+                       if (other.objects != null)
+                               return false;
+               } else if (!this.objects.equals(other.objects))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPMessage [objects=");
+               builder.append(this.objects);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPOFCodes.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPOFCodes.java
new file mode 100644 (file)
index 0000000..7bcedbd
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+/**
+ * Enumerable representing ObjectiveFunction codes. Defined in RFC5541.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc5541#section-4">Objective
+ *      Functions Definition</a>
+ * @see <a href="http://tools.ietf.org/html/rfc6006#section-3.6.1">New Objective
+ *      Functions [RFC6006]</a>
+ */
+public enum PCEPOFCodes {
+       /**
+        * Minimum Cost Path
+        */
+       MCP,
+       /**
+        * Minimum Load Path
+        */
+       MLP,
+       /**
+        * Maximum residual Bandwidth Path
+        */
+       MBP,
+       /**
+        * Minimize aggregate Bandwidth Consumption
+        */
+       MBC,
+       /**
+        * Minimize the load of the Most Loaded Link
+        */
+       MLL,
+       /**
+        * Minimize Cumulative Cost of a set of paths
+        */
+       MCC,
+       /**
+        * Name: Shortest Path Tree (SPT)
+        * 
+        * Description: Minimize the maximum source-to-leaf cost with respect to a
+        * specific metric or to the TE metric used as the default metric when the
+        * metric is not specified (e.g., TE or IGP metric).
+        */
+       SPT,
+       /**
+        * Name: Minimum Cost Tree (MCT)
+        * 
+        * Description: Minimize the total cost of the tree, that is the sum of the
+        * costs of tree links, with respect to a specific metric or to the TE
+        * metric used as the default metric when the metric is not specified.
+        */
+       MCT;
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPObject.java
new file mode 100644 (file)
index 0000000..c847ddd
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Basic structure for PCEP Objects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.2">Common Object
+ *      Header</a>
+ */
+public abstract class PCEPObject {
+
+       private final boolean processed;
+
+       private final boolean ignored;
+
+       /**
+        * Constructor is protected to prevent direct instantiation, but to allow to
+        * call this constructor via super().
+        *
+        * @param processed
+        *            P flag
+        * @param ignored
+        *            I flag
+        */
+       protected PCEPObject(boolean processed, boolean ignored) {
+               this.processed = processed;
+               this.ignored = ignored;
+       }
+
+       /**
+        * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.2"> Common
+        *      Object Header</a>
+        *
+        * @return true if P flag is set and false if is not.
+        */
+       public boolean isProcessed() {
+               return this.processed;
+       }
+
+       /**
+        * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.2"> Common
+        *      Object Header</a>
+        *
+        * @return true if I flag is set and false if is not.
+        */
+       public boolean isIgnored() {
+               return this.ignored;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (this.ignored ? 1231 : 1237);
+               result = prime * result + (this.processed ? 1231 : 1237);
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPObject other = (PCEPObject) obj;
+               if (this.ignored != other.ignored)
+                       return false;
+               if (this.processed != other.processed)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString(){
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("processed", this.processed);
+               toStringHelper.add("ignored", this.ignored);
+               return toStringHelper;
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSession.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSession.java
new file mode 100644 (file)
index 0000000..df7573c
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import java.io.Closeable;
+
+/**
+ * PCEP Session represents the finite state machine in PCEP,
+ * including timers and its purpose is to create a PCEP connection
+ * between PCE/PCC. Session is automatically started, when TCP
+ * connection is created, but can be stopped manually.
+ * If the session is up, it has to redirect messages to/from user.
+ * Handles also malformed messages and unknown requests.
+ */
+public interface PCEPSession extends Closeable {
+
+       /**
+        * Sends message from user to PCE/PCC. If the user sends an Open
+        * Message, the session returns an error (open message is only
+        * allowed, when a PCEP handshake is in progress). Close message
+        * will close the session and free all the resources.
+        * @param message message to be sent
+        */
+       public void sendMessage(PCEPMessage message);
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionFactory.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionFactory.java
new file mode 100644 (file)
index 0000000..c6c8499
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import java.util.Timer;
+
+import org.opendaylight.protocol.framework.ProtocolConnection;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.ProtocolSessionFactory;
+import org.opendaylight.protocol.framework.SessionParent;
+
+public interface PCEPSessionFactory extends ProtocolSessionFactory {
+       @Override
+       public ProtocolSession getProtocolSession(SessionParent parent, Timer timer, ProtocolConnection connection, int sessionId);
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionListener.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionListener.java
new file mode 100644 (file)
index 0000000..cc568f3
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import org.opendaylight.protocol.framework.SessionListener;
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ *     Listener that receives session informations from the session.
+ */
+public abstract class PCEPSessionListener implements SessionListener {
+
+       /**
+        * Fired when a message is received.
+        * @param session session which received the message
+        * @param message PCEPMessage
+        */
+       public abstract void onMessage(PCEPSession session, PCEPMessage message);
+
+       /**
+        * Fired when the session is in state UP.
+        *
+        * @param session Session which went up
+        * @param local Local open proposal which the peer accepted
+        * @param remote Peer open proposal which we accepted
+        */
+       public abstract void onSessionUp(PCEPSession session, PCEPOpenObject local, PCEPOpenObject remote);
+
+       /**
+        * Fired when the session went down as a result of peer's decision
+        * to tear it down.
+        * Implementation should take care of closing underlying session.
+        *
+        * @param session Session which went down
+        * @param reason Reason for termination, may be null when the underlying
+        *               channel was closed without a specific reason.
+        * @param e exception that caused session down
+        */
+       public abstract void onSessionDown(PCEPSession session, PCEPCloseObject reason, Exception e);
+
+       /**
+        * Fired when the session is terminated locally. The session has already
+        * been closed and transitioned to IDLE state. Any outstanding queued
+        * messages were not sent. The user should not attempt to make any use
+        * of the session.
+        *
+        * @param session Session which went down
+        * @param cause the cause why the session went down
+        */
+       public abstract void onSessionTerminated(PCEPSession session, TerminationReason cause);
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionListenerFactory.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionListenerFactory.java
new file mode 100644 (file)
index 0000000..20f4a39
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import java.net.InetAddress;
+
+import org.opendaylight.protocol.framework.SessionListenerFactory;
+
+/**
+ * Factory for generating PCEP Session Listeners. Used by a server.
+ */
+public abstract class PCEPSessionListenerFactory implements SessionListenerFactory {
+
+       /**
+        * Returns one session listener that is registered to this factory
+        * @param address serves as constraint, so that factory is able to
+        * return different listeners for different factories
+        * @return specific session listener
+        */
+       @Override
+       public abstract PCEPSessionListener getSessionListener(InetAddress address);
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionPreferences.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionPreferences.java
new file mode 100644 (file)
index 0000000..e881135
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Implementation of {@link SessionPreferences}.
+ */
+public final class PCEPSessionPreferences implements SessionPreferences {
+
+       private final PCEPOpenObject openObject;
+
+       /**
+        * Construct new session preferences.
+        *
+        * @param openObject encapsulated PCEP OPEN object
+        */
+       public PCEPSessionPreferences(final PCEPOpenObject openObject) {
+               this.openObject = openObject;
+       }
+
+       /**
+        * Return the encapsulated OPEN object.
+        *
+        * @return encapsulated OPEN object.
+        */
+       public PCEPOpenObject getOpenObject() {
+               return this.openObject;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result
+                               + ((this.openObject == null) ? 0 : this.openObject.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof PCEPSessionPreferences))
+                       return false;
+               final PCEPSessionPreferences other = (PCEPSessionPreferences) obj;
+               if (this.openObject == null) {
+                       if (other.openObject != null)
+                               return false;
+               } else if (!this.openObject.equals(other.openObject))
+                       return false;
+               return true;
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposal.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposal.java
new file mode 100644 (file)
index 0000000..aa41f72
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import org.opendaylight.protocol.framework.SessionProposal;
+
+/**
+ * Interface that provides the initial acceptable session characteristics
+ * with which the session should be started.
+ */
+public abstract class PCEPSessionProposal implements SessionProposal {
+
+       /**
+        * Returns specific PCEPOpenObject for this IP address.
+        * @param address serves as constraint, the implementation can also
+        * take time into consideration
+        * @return PCEPOpenObject with acceptable session characteristics
+        */
+       @Override
+       public abstract PCEPSessionPreferences getProposal();
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposalChecker.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposalChecker.java
new file mode 100644 (file)
index 0000000..a1ac3fd
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.framework.SessionPreferencesChecker;
+
+/**
+ * Interface to work with session characteristics. They need to be
+ * checked during the PCEP establishment phase. If they are not
+ * acceptable a new proposal needs to be requested.
+ */
+public abstract class PCEPSessionProposalChecker implements SessionPreferencesChecker {
+
+       /**
+        * Checks session characteristics, if they are acceptable.
+        *
+        * @param openObj
+        *            storage for session characteristics
+        * @return true = acceptable, false = negotiable, null = unacceptable
+        */
+       @Override
+       public abstract Boolean checkSessionCharacteristics(SessionPreferences openObj);
+
+       /**
+        * In case of negotiable session characteristics, new ones are requested
+        * through this method.
+        *
+        * @param open old open object with unacceptable session characteristics
+        * @return
+        *      <li> new session characteristics wrapped in Open Object
+        *      <li> null if there are not available any different acceptable
+        * session characteristics
+        */
+       public abstract PCEPSessionPreferences getNewProposal(SessionPreferences open);
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposalCheckerFactory.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposalCheckerFactory.java
new file mode 100644 (file)
index 0000000..d796425
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.SessionPreferencesCheckerFactory;
+
+/**
+ * Factory for generating PCEP Session Proposal Checkers. Used by a server.
+ */
+public abstract class PCEPSessionProposalCheckerFactory implements SessionPreferencesCheckerFactory {
+
+       /**
+        * Returns one session proposal checker that is registered to this factory
+        * @param address serves as constraint, so that factory is able to
+        * return different checkers for different factories
+        * @return specific session proposal checker
+        */
+       @Override
+       public abstract PCEPSessionProposalChecker getPreferencesChecker(InetSocketAddress address);
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposalFactory.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSessionProposalFactory.java
new file mode 100644 (file)
index 0000000..9f6a5a1
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.SessionProposalFactory;
+
+/**
+ * Factory for generating PCEP Session proposals. Used by a server.
+ */
+public abstract class PCEPSessionProposalFactory implements SessionProposalFactory {
+
+       /**
+        * Returns one session proposal that is registered to this factory
+        *
+        * @param address
+        *            serves as constraint, so that factory is able to return
+        *            different proposals for different addresses
+        * @param sessionId
+        *            is used for creation of PCEPOpenObject
+        * @return specific session proposal
+        */
+       @Override
+       public abstract PCEPSessionProposal getSessionProposal(InetSocketAddress address, int sessionId);
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPTlv.java
new file mode 100644 (file)
index 0000000..d108489
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep;
+
+import java.io.Serializable;
+
+/**
+ * Interface grouping all implemented tlvs.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.1">PCEP TLV
+ *      Format</a>
+ */
+public interface PCEPTlv extends Serializable {
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/AbstractExtendedTunnelIdentifier.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/AbstractExtendedTunnelIdentifier.java
new file mode 100644 (file)
index 0000000..2b031cf
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * Basic structure of Extended Tunnel Identifier.
+ * 
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ *      Identifiers TLVs</a>
+ * @param <T>
+ */
+public abstract class AbstractExtendedTunnelIdentifier<T extends NetworkAddress<T>> implements Comparable<ExtendedTunnelIdentifier<T>>, ExtendedTunnelIdentifier<T> {
+
+       private static final long serialVersionUID = 110737862492677555L;
+
+       private final T identifier;
+
+       protected AbstractExtendedTunnelIdentifier(final T identifier) {
+               this.identifier = identifier;
+       }
+
+       @Override
+       public T getIdentifier() {
+               return this.identifier;
+       }
+
+       @Override
+       public int compareTo(final ExtendedTunnelIdentifier<T> other) {
+               if (this.identifier == other.getIdentifier())
+                       return 0;
+               if (this.identifier == null)
+                       return -1;
+               if (other.getIdentifier() == null)
+                       return 1;
+               return this.identifier.compareTo(other.getIdentifier());
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.identifier == null) ? 0 : this.identifier.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final AbstractExtendedTunnelIdentifier<?> other = (AbstractExtendedTunnelIdentifier<?>) obj;
+               if (this.identifier == null) {
+                       if (other.identifier != null)
+                               return false;
+               } else if (!this.identifier.equals(other.identifier))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("AbstractExtendedTunnelIdentifier [identifier=");
+               builder.append(this.identifier);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/AggregateBandwidthConsumptionMetric.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/AggregateBandwidthConsumptionMetric.java
new file mode 100644 (file)
index 0000000..f2ba955
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * Aggregate Bandwidth Consumption metric class.
+ */
+public class AggregateBandwidthConsumptionMetric extends AbstractMetric<AggregateBandwidthConsumptionMetric> {
+
+       private static final long serialVersionUID = 3935025327997428991L;
+
+       /**
+        * Construct a new Aggregate Bandwidth Consumption metric object.
+        * 
+        * @param value
+        *            Metric value
+        * @throws IllegalArgumentException
+        *             ex when value is outside of allowed range (0-4294967295)
+        */
+       public AggregateBandwidthConsumptionMetric(final long value) {
+               super(value);
+               if (value < 0 || value > 4294967295L)
+                       throw new IllegalArgumentException("Invalid Agregate Bandwidth Consumption metric value");
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/CumulativeIGPCostMetric.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/CumulativeIGPCostMetric.java
new file mode 100644 (file)
index 0000000..b850462
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * Cumulative IGP cost metric class
+ */
+public class CumulativeIGPCostMetric extends AbstractMetric<CumulativeIGPCostMetric> {
+
+       private static final long serialVersionUID = 3935025327997428991L;
+
+       /**
+        * Construct a new Cumulative IGP cost metric object.
+        * 
+        * @param value
+        *            Metric value
+        * @throws IllegalArgumentException
+        *             ex when value is outside of allowed range (0-4294967295)
+        */
+       public CumulativeIGPCostMetric(final long value) {
+               super(value);
+               if (value < 0 || value > 4294967295L)
+                       throw new IllegalArgumentException("Invalid cumulative IGP cost metric value");
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/CumulativeTECostMetric.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/CumulativeTECostMetric.java
new file mode 100644 (file)
index 0000000..2a3ce3b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * Cumulative TE cost metric class
+ */
+public class CumulativeTECostMetric extends AbstractMetric<CumulativeTECostMetric> {
+
+       private static final long serialVersionUID = 3935025327997428991L;
+
+       /**
+        * Construct a new Cumulative TE cost metric object.
+        * 
+        * @param value
+        *            Metric value
+        * @throws IllegalArgumentException
+        *             ex when value is outside of allowed range (0-4294967295)
+        */
+       public CumulativeTECostMetric(final long value) {
+               super(value);
+               if (value < 0 || value > 4294967295L)
+                       throw new IllegalArgumentException("Invalid cumulative TE cost metric value");
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/ExtendedTunnelIdentifier.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/ExtendedTunnelIdentifier.java
new file mode 100644 (file)
index 0000000..7eb9110
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * Interface grouping Extended Tunnel Identifiers.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ *      Identifiers TLVs</a>
+ * @param <T> IPv4 or IPv6 address that is wrapped in this tunnel
+ */
+public interface ExtendedTunnelIdentifier<T extends NetworkAddress<T>> extends Identifier {
+
+       /**
+        * Getter for Identifier of Extended Tunnel.
+        *
+        * @return T IPv4 or IPv6 address
+        */
+       public T getIdentifier();
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/IPv4ExtendedTunnelIdentifier.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/IPv4ExtendedTunnelIdentifier.java
new file mode 100644 (file)
index 0000000..65891e3
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * Specific structure of IPv4 Extended Tunnel Identifier.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ *      Identifiers TLVs</a>
+ */
+public final class IPv4ExtendedTunnelIdentifier extends AbstractExtendedTunnelIdentifier<IPv4Address> {
+
+       private static final long serialVersionUID = -8872936514548777175L;
+
+       /**
+        * Creates IPv4ExtendedTunnelIdentifier with given IPv4Address.
+        * @param routerAddress {@link IPv4Address}
+        */
+       public IPv4ExtendedTunnelIdentifier(final IPv4Address routerAddress) {
+               super(routerAddress);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/IPv6ExtendedTunnelIdentifier.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/IPv6ExtendedTunnelIdentifier.java
new file mode 100644 (file)
index 0000000..036b885
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+
+/**
+ * Specific structure of IPv6 Extended Tunnel Identifier.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ *      Identifiers TLVs</a>
+ */
+public final class IPv6ExtendedTunnelIdentifier extends AbstractExtendedTunnelIdentifier<IPv6Address> {
+
+       private static final long serialVersionUID = -4603732260818370518L;
+
+       /**
+        * Creates IPv6ExtendedTunnelIdentifier with given IPv6Address.
+        * @param routerAddress {@link IPv6Address}
+        */
+       public IPv6ExtendedTunnelIdentifier(final IPv6Address routerAddress) {
+               super(routerAddress);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/LSPIdentifier.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/LSPIdentifier.java
new file mode 100644 (file)
index 0000000..f5b978f
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * A 16-bit identifier used in the SENDER_TEMPLATE and the FILTER_SPEC that can
+ * be changed to allow a sender to share resources with itself.
+ */
+public final class LSPIdentifier extends AbstractIdentifier<LSPIdentifier> {
+
+       private static final long serialVersionUID = 1337756730239265010L;
+
+       private final byte[] lspId;
+
+       /**
+        * Creates LSPIdentifier using byte array as value.
+        *
+        * @param lspId
+        *            value of the LSPIdentifier TLV. Must be exactly 2 bytes long.
+        */
+       public LSPIdentifier(final byte[] lspId) {
+               if (lspId.length != 2)
+                       throw new IllegalArgumentException("Invalid LSP identifier");
+               this.lspId = lspId;
+       }
+
+       /**
+        * Gets LSP Id in raw byte array representation.
+        *
+        * @return byte array representation of LSP ID. May be null.
+        */
+       public byte[] getLspId() {
+               return this.lspId;
+       }
+
+       @Override
+       protected byte[] getBytes() {
+               return this.lspId;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("lspId", ByteArray.toHexString(lspId, "."));
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/LSPSymbolicName.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/LSPSymbolicName.java
new file mode 100644 (file)
index 0000000..40931fc
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.1">The
+ *      LSP Symbolic Name TLV</a>
+ */
+public final class LSPSymbolicName extends AbstractIdentifier<LSPSymbolicName> {
+
+       private static final long serialVersionUID = -5649378295100912021L;
+
+       private final byte[] symbolicName;
+
+       /**
+        * Creates LSPSymbolicName using byte array as value.
+        *
+        * @param symbolicName
+        *            value of the LSPSymbolicName TLV
+        */
+       public LSPSymbolicName(final byte[] symbolicName) {
+               this.symbolicName = symbolicName;
+       }
+
+       /**
+        * Gets Symbolic Name in raw byte array representation.
+        *
+        * @return byte array representation of Symbolic Name. May be null.
+        */
+       public byte[] getSymbolicName() {
+               return this.symbolicName;
+       }
+
+       @Override
+       protected byte[] getBytes() {
+               return this.symbolicName;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("symbolicName", ByteArray.toHexString(symbolicName, "."));
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/MostLoadedLinkLoadMetric.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/MostLoadedLinkLoadMetric.java
new file mode 100644 (file)
index 0000000..762fdb1
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * Load of the most loaded link metric class
+ */
+public class MostLoadedLinkLoadMetric extends AbstractMetric<MostLoadedLinkLoadMetric> {
+
+       private static final long serialVersionUID = 3935025327997428991L;
+
+       /**
+        * Construct a new Load of the most loaded link metric object.
+        * 
+        * @param value
+        *            Metric value
+        * @throws IllegalArgumentException
+        *             ex when value is outside of allowed range (0-4294967295)
+        */
+       public MostLoadedLinkLoadMetric(final long value) {
+               super(value);
+               if (value < 0 || value > 4294967295L)
+                       throw new IllegalArgumentException("Invalid Load of the most loaded link metric value");
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/P2MPHopCountMetric.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/P2MPHopCountMetric.java
new file mode 100644 (file)
index 0000000..be2a0f6
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * P2MP hop count metric class
+ */
+public class P2MPHopCountMetric extends AbstractMetric<P2MPHopCountMetric> {
+
+       private static final long serialVersionUID = 3935025327997428991L;
+
+       /**
+        * Construct a new P2MP hop count metric object.
+        * 
+        * @param value
+        *            Metric value
+        * @throws IllegalArgumentException
+        *             ex when value is outside of allowed range (0-4294967295)
+        */
+       public P2MPHopCountMetric(final long value) {
+               super(value);
+               if (value < 0 || value > 4294967295L)
+                       throw new IllegalArgumentException("Invalid P2MP hop count metric value");
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/P2MPIGPMetric.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/P2MPIGPMetric.java
new file mode 100644 (file)
index 0000000..c8e3f91
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * P2MP IGP metric class
+ */
+public class P2MPIGPMetric extends AbstractMetric<P2MPIGPMetric> {
+
+       private static final long serialVersionUID = 3935025327997428991L;
+
+       /**
+        * Construct a new P2MP IGP metric metric object.
+        * 
+        * @param value
+        *            Metric value
+        * @throws IllegalArgumentException
+        *             ex when value is outside of allowed range (0-4294967295)
+        */
+       public P2MPIGPMetric(final long value) {
+               super(value);
+               if (value < 0 || value > 4294967295L)
+                       throw new IllegalArgumentException("Invalid P2MP IGP metric value");
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/P2MPTEMetric.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/P2MPTEMetric.java
new file mode 100644 (file)
index 0000000..74cc34e
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * P2MP TE metric class
+ */
+public class P2MPTEMetric extends AbstractMetric<P2MPTEMetric> {
+
+       private static final long serialVersionUID = 3935025327997428991L;
+
+       /**
+        * Construct a new P2MP TE metric object.
+        * 
+        * @param value
+        *            Metric value
+        * @throws IllegalArgumentException
+        *             ex when value is outside of allowed range (0-4294967295)
+        */
+       public P2MPTEMetric(final long value) {
+               super(value);
+               if (value < 0 || value > 4294967295L)
+                       throw new IllegalArgumentException("Invalid P2MP TE metri value");
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/TunnelIdentifier.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/TunnelIdentifier.java
new file mode 100644 (file)
index 0000000..c4859b1
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * A 16-bit identifier used in the SESSION that remains constant over the life
+ * of the tunnel.
+ */
+public final class TunnelIdentifier extends AbstractIdentifier<TunnelIdentifier> {
+
+       private static final long serialVersionUID = 137237703900885441L;
+
+       private final byte[] tunnelId;
+
+       /**
+        * Creates TunnelIdentifier using byte array as value.
+        *
+        * @param tunnelId
+        *            value of the TunnelIdentifier TLV. Must be exactly 2 bytes
+        *            long.
+        */
+       public TunnelIdentifier(final byte[] tunnelId) {
+               if (tunnelId.length != 2)
+                       throw new IllegalArgumentException("Invalid tunnel ID.");
+               this.tunnelId = tunnelId;
+       }
+
+       @Override
+       public byte[] getBytes() {
+               return this.tunnelId;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+               return toStringHelper.add("tunnelId", ByteArray.toHexString(tunnelId, "."));
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/UnnumberedInterfaceIdentifier.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/concepts/UnnumberedInterfaceIdentifier.java
new file mode 100644 (file)
index 0000000..601ebf6
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+/**
+ * A 32-bit (unsigned) identifying an interface within a router. This identifier
+ * is explicitly local to the router, e.g. each router has its own namespace.
+ */
+public final class UnnumberedInterfaceIdentifier implements Comparable<UnnumberedInterfaceIdentifier>, Identifier {
+
+       private static final long serialVersionUID = -8488014237579913120L;
+
+       private final long interfaceId;
+
+       /**
+        * Creates an instance of UnnumberedInterfaceIdentifier from long number.
+        * 
+        * @param interfaceId
+        *            long the value of the UnnumberedInterfaceIdentifier
+        */
+       public UnnumberedInterfaceIdentifier(final long interfaceId) {
+               if (interfaceId < 0 || interfaceId > 4294967295L)
+                       throw new IllegalArgumentException("Invalid link identifier");
+               this.interfaceId = interfaceId;
+       }
+
+       /**
+        * Getter for Interface Id represented as long.
+        * 
+        * @return long representation of Interface Id. From 0 to 4294967295.
+        */
+       public long getInterfaceId() {
+               return this.interfaceId;
+       }
+
+       @Override
+       public int compareTo(final UnnumberedInterfaceIdentifier o) {
+               if (this.interfaceId < o.getInterfaceId())
+                       return -1;
+               if (this.interfaceId > o.getInterfaceId())
+                       return 1;
+               return 0;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (int) (this.interfaceId ^ (this.interfaceId >>> 32));
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final UnnumberedInterfaceIdentifier other = (UnnumberedInterfaceIdentifier) obj;
+               if (this.interfaceId != other.interfaceId)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("UnnumberedInterfaceIdentifier [interfaceId=");
+               builder.append(this.interfaceId);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCCreateMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCCreateMessage.java
new file mode 100644 (file)
index 0000000..df64f48
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeInstantiationObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+
+/**
+ * @see <a href="http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt">5.1.  The LSP Create Message</a>
+ */
+public class PCCreateMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = -2407399568579836171L;
+
+       private final List<CompositeInstantiationObject> lsps;
+
+       /**
+        * Constructs {@link PCCreateMessage}.
+        *
+        * @throws IllegalArgumentException
+        *             if there is not even one {@link CompositeInstantiationObject}
+        *             in the list.
+        *
+        * @param lsps
+        *            List<CompositeInstantiationObject>. Can't be empty or null.
+        */
+       public PCCreateMessage(final List<CompositeInstantiationObject> lsps) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               if (lsps != null)
+                                       for (final CompositeInstantiationObject cio : lsps) {
+                                               this.addAll(cio.getCompositeAsList());
+                                       }
+                       }
+               });
+               if (lsps == null || lsps.isEmpty())
+                       throw new IllegalArgumentException("At least one CompositeStateReportObject is mandatory.");
+
+               this.lsps = lsps;
+       }
+
+       /**
+        * Gets list of {@link CompositeStateReportObject}.
+        *
+        * @return List<CompositeStateReportObject>. Can't be null or empty.
+        */
+       public List<CompositeInstantiationObject> getLSPs() {
+               return this.lsps;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.lsps == null) ? 0 : this.lsps.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (!(obj instanceof PCCreateMessage))
+                       return false;
+               final PCCreateMessage other = (PCCreateMessage) obj;
+               if (this.lsps == null) {
+                       if (other.lsps != null)
+                               return false;
+               } else if (!this.lsps.equals(other.lsps))
+                       return false;
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCCreateMessage [lsps=");
+               builder.append(this.lsps);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPCloseMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPCloseMessage.java
new file mode 100644 (file)
index 0000000..5426f99
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+
+/**
+ * Structure of Close Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.8">Close
+ *      Message</a>
+ */
+public class PCEPCloseMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = -2365304678646268281L;
+
+       private final PCEPCloseObject closeObj;
+
+       /**
+        * Constructs a new Close Message, which has to include PCEP Close Object.
+        * Is used to close an established session between PCEP Peers.
+        *
+        * @throws IllegalArgumentException
+        *             if the CloseObject passed, is null.
+        *
+        * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.8">Close
+        *      Message</a>
+        *
+        * @param closeObj
+        *            Can't be null.
+        */
+       public PCEPCloseMessage(final PCEPCloseObject closeObj) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = -8094080277421295531L;
+
+                       {
+                               if (closeObj != null)
+                                       this.add(closeObj);
+                       }
+               });
+               if (closeObj == null)
+                       throw new IllegalArgumentException("PCEPCloseObject is mandatory. Can't be null.");
+
+               this.closeObj = closeObj;
+       }
+
+       /**
+        * Gets {@link PCEPCloseObject}, which is mandatory object of PCEP Close
+        * Message.
+        *
+        * @return {@link PCEPCloseObject} . Can't be null.
+        */
+       public PCEPCloseObject getCloseObject() {
+               return this.closeObj;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.closeObj == null) ? 0 : this.closeObj.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPCloseMessage other = (PCEPCloseMessage) obj;
+               if (this.closeObj == null) {
+                       if (other.closeObj != null)
+                               return false;
+               } else if (!this.closeObj.equals(other.closeObj))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPCloseMessage [closeObj=");
+               builder.append(this.closeObj);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPErrorMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPErrorMessage.java
new file mode 100644 (file)
index 0000000..868a5ce
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Structure of Error Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.7">Error
+ *      Message</a>
+ */
+public class PCEPErrorMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = 604782651368689577L;
+
+       private PCEPOpenObject openObj;
+
+       private final List<PCEPErrorObject> errorObjects;
+
+       private final List<CompositeErrorObject> errors;
+
+       public PCEPErrorMessage(final PCEPErrorObject errorObject) {
+               this(new ArrayList<PCEPErrorObject>() {
+                       private static final long serialVersionUID = 72172137965955228L;
+
+                       {
+                               this.add(errorObject);
+                       }
+               });
+       }
+
+       public PCEPErrorMessage(final CompositeErrorObject compositeErrorObject) {
+               this(new ArrayList<CompositeErrorObject>() {
+                       private static final long serialVersionUID = 72172137965955228L;
+
+                       {
+                               if (compositeErrorObject != null)
+                                       this.add(compositeErrorObject);
+                       }
+               });
+       }
+
+       /**
+        * Constructs Error Message from list of {@link PCEPErrorObject} or
+        * {@link CompositeErrorObject}.
+        *
+        * @param errorObjects
+        *            List<?> either objects of type: {@link PCEPErrorObject} or
+        *            {@link CompositeErrorObject}
+        *
+        * @throws IllegalArgumentException
+        *             if any other type is passed in the list, that cannot be
+        *             processed
+        */
+       public PCEPErrorMessage(final List<?> errorObjects) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = -8607527575304297642L;
+
+                       {
+                               if (errorObjects != null)
+                                       for (int i = 0; i < errorObjects.size(); i++) {
+                                               if (errorObjects.get(i) instanceof CompositeErrorObject) {
+                                                       this.addAll(((CompositeErrorObject) errorObjects.get(i)).getCompositeAsList());
+                                               } else if (errorObjects.get(i) instanceof PCEPErrorObject) {
+                                                       this.add((PCEPErrorObject) errorObjects.get(i));
+                                               }
+                                       }
+                       }
+               });
+               this.errors = new ArrayList<CompositeErrorObject>();
+               this.errorObjects = new ArrayList<PCEPErrorObject>();
+
+               if (errorObjects != null) {
+                       for (int i = 0; i < errorObjects.size(); i++) {
+                               if (errorObjects.get(i) instanceof CompositeErrorObject) {
+                                       this.errors.add((CompositeErrorObject) errorObjects.get(i));
+                               } else if (errorObjects.get(i) instanceof PCEPErrorObject) {
+                                       this.errorObjects.add((PCEPErrorObject) errorObjects.get(i));
+                               } else
+                                       throw new IllegalArgumentException("Wrong instance passed in list. Acceptable is only CompositeErrorObject or PCEPErrorObject.");
+                       }
+               }
+       }
+
+       /**
+        * Constructs Error Message from list of {@link PCEPErrorObject} and
+        * {@link CompositeErrorObject} and {@link PCEPOpenObject} that cannot be
+        * null. This constructor is used during PCEP handshake to suggest new
+        * session characteristics for the session that are listen in
+        * {@link PCEPOpenObject}.
+        *
+        * @param openObj
+        *            {@link PCEPOpenObject} cannot be null
+        * @param errorObjects
+        *            List<PCEPErrorObject> list of error objects
+        * @param errors
+        *            List<CompositeErrorObject> list of composite error objects
+        */
+       public PCEPErrorMessage(final PCEPOpenObject openObj, final List<PCEPErrorObject> errorObjects, final List<CompositeErrorObject> errors) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = -4238105145756981972L;
+
+                       {
+                               if (errorObjects != null)
+                                       this.addAll(errorObjects);
+                               if (openObj != null)
+                                       this.add(openObj);
+                               if (errors != null)
+                                       for (final CompositeErrorObject ceo : errors) {
+                                               this.addAll(ceo.getCompositeAsList());
+                                       }
+                       }
+               });
+               this.openObj = openObj;
+
+               if (errorObjects == null)
+                       throw new IllegalArgumentException("At least one PCEPErrorObject is mandatory.");
+               this.errorObjects = errorObjects;
+
+               if (errors == null)
+                       this.errors = Collections.emptyList();
+               else
+                       this.errors = errors;
+       }
+
+       /**
+        * Gets {@link PCEPOpenObject} if this is included. If its included, it
+        * proposes alternative acceptable session characteristic values.
+        *
+        * @return PCEPOpenObject. May be null.
+        */
+       public PCEPOpenObject getOpenObject() {
+               return this.openObj;
+       }
+
+       /**
+        * In unsolicited manner can be included List of
+        * <code>PCEPErrorObjects</code> <code>PCEPErrorMessage</code>, which is not
+        * sent in response to a request.
+        *
+        * @return List<PCEPErrorObject>
+        */
+       public List<PCEPErrorObject> getErrorObjects() {
+               return this.errorObjects;
+       }
+
+       /**
+        * If the PCErr message is sent in response to a request, the PCErr message
+        * MUST include set of RP objects related to pending path computation
+        * requests that triggered the error condition. In this situation it is
+        * constructed as {@link org.opendaylight.protocol.pcep.object.CompositeErrorObject
+        * CompCompositeErrorObject}. That includes list of RP objects.
+        *
+        * @return CompositeErrorObject. May be null.
+        */
+       public List<CompositeErrorObject> getErrors() {
+               return this.errors;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.errorObjects == null) ? 0 : this.errorObjects.hashCode());
+               result = prime * result + ((this.errors == null) ? 0 : this.errors.hashCode());
+               result = prime * result + ((this.openObj == null) ? 0 : this.openObj.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPErrorMessage other = (PCEPErrorMessage) obj;
+               if (this.errorObjects == null) {
+                       if (other.errorObjects != null)
+                               return false;
+               } else if (!this.errorObjects.equals(other.errorObjects))
+                       return false;
+               if (this.errors == null) {
+                       if (other.errors != null)
+                               return false;
+               } else if (!this.errors.equals(other.errors))
+                       return false;
+               if (this.openObj == null) {
+                       if (other.openObj != null)
+                               return false;
+               } else if (!this.openObj.equals(other.openObj))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPErrorMessage [openObj=");
+               builder.append(this.openObj);
+               builder.append(", errorObjects=");
+               builder.append(this.errorObjects);
+               builder.append(", errors=");
+               builder.append(this.errors);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPKeepAliveMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPKeepAliveMessage.java
new file mode 100644 (file)
index 0000000..77a6e85
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.Collections;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure of Keepalive Message
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.3">KeepAlive
+ *      Message</a>
+ */
+public final class PCEPKeepAliveMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = 8133032616718362219L;
+
+       /**
+        * Default constructor PCEPKeepAliveMessage.
+        */
+       public PCEPKeepAliveMessage() {
+               super(Collections.<PCEPObject> emptyList());
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPKeepAliveMessage []");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPNotificationMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPNotificationMessage.java
new file mode 100644 (file)
index 0000000..b9fb652
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+
+/**
+ * Structure of Notification Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.6">Notification
+ *      Message</a>
+ */
+public class PCEPNotificationMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = 2647656169727976386L;
+
+       private final List<CompositeNotifyObject> notifications;
+
+       /**
+        * Constructs new Notification Message.
+        *
+        * @throws IllegalArgumentException
+        *             if there is not even one {@link CompositeNotifyObject} in the
+        *             list.
+        *
+        * @param notifications
+        *            List<CompositeNotifyObject>. Can't be empty or null.
+        */
+       public PCEPNotificationMessage(final List<CompositeNotifyObject> notifications) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = 8359665614469883203L;
+
+                       {
+                               if (notifications != null)
+                                       for (final CompositeNotifyObject cno : notifications) {
+                                               this.addAll(cno.getCompositeAsList());
+                                       }
+                       }
+               });
+
+               if (notifications == null || notifications.isEmpty())
+                       throw new IllegalArgumentException("At least one CompositeNotifyObject is mandatory.");
+
+               this.notifications = notifications;
+       }
+
+       /**
+        * Gets list of {@link org.opendaylight.protocol.pcep.object.CompositeNotifyObject
+        * CompositeNotifyObjects}.
+        *
+        * @return List<CompositeNotifyObject>. Can't be null or empty.
+        */
+       public List<CompositeNotifyObject> getNotifications() {
+               return this.notifications;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.notifications == null) ? 0 : this.notifications.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPNotificationMessage other = (PCEPNotificationMessage) obj;
+               if (this.notifications == null) {
+                       if (other.notifications != null)
+                               return false;
+               } else if (!this.notifications.equals(other.notifications))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPNotificationMessage [notifications=");
+               builder.append(this.notifications);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPOpenMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPOpenMessage.java
new file mode 100644 (file)
index 0000000..34ab8d2
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Structure of Open Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.2">Open
+ *      Message</a>
+ */
+public class PCEPOpenMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = -588927926753235030L;
+
+       private final PCEPOpenObject openObj;
+
+       /**
+        * Constructs new Open Message.
+        *
+        * @throws IllegalArgumentException
+        *             if the PCEPOpenObject is null.
+        *
+        * @param openObj
+        *            {@link PCEPOpenObject}. Can't be null.
+        */
+       public PCEPOpenMessage(final PCEPOpenObject openObj) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = -1339062869814655362L;
+
+                       {
+                               if (openObj != null)
+                                       this.add(openObj);
+                       }
+               });
+
+               if (openObj == null)
+                       throw new IllegalArgumentException("PCEPOpenObject is mandatory.");
+
+               this.openObj = openObj;
+       }
+
+       /**
+        * Gets {@link PCEPOpenObject}
+        *
+        * @return {@link PCEPOpenObject}. Can't be null.
+        */
+       public PCEPOpenObject getOpenObject() {
+               return this.openObj;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.openObj == null) ? 0 : this.openObj.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPOpenMessage other = (PCEPOpenMessage) obj;
+               if (this.openObj == null) {
+                       if (other.openObj != null)
+                               return false;
+               } else if (!this.openObj.equals(other.openObj))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPOpenMessage [openObj=");
+               builder.append(this.openObj);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPReplyMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPReplyMessage.java
new file mode 100644 (file)
index 0000000..56208dc
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeReplySvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+
+/**
+ * Structure for Reply Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.5">Reply
+ *      Message</a>
+ */
+public class PCEPReplyMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = -4604680426345882626L;
+
+       private final List<CompositeReplySvecObject> svecList;
+
+       private final List<CompositeResponseObject> responses;
+
+       /**
+        * Constructs new Reply Message.
+        *
+        * @throws IllegalArgumentException
+        *             if there is not even one {@link CompositeResponseObject} in
+        *             the list.
+        *
+        * @param responses
+        *            List<CompositeResponseObject>. Can't be empty or null.
+        */
+       public PCEPReplyMessage(final List<CompositeResponseObject> responses) {
+               this(responses, null);
+       }
+
+       /**
+        * Constructs {@link PCEPReplyMessage}.
+        *
+        * @throws IllegalArgumentException
+        *             if there is not even one {@link CompositeResponseObject} in
+        *             the list.
+        *
+        * @param svecList
+        *            List<CompositeSvecObject>
+        * @param responses
+        *            List<CompositeResponseObject>. Can't be empty or null.
+        */
+       public PCEPReplyMessage(final List<CompositeResponseObject> responses, final List<CompositeReplySvecObject> svecList) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = 4464502017081110298L;
+
+                       {
+                               if (svecList != null)
+                                       for (final CompositeReplySvecObject cno : svecList) {
+                                               this.addAll(cno.getCompositeAsList());
+                                       }
+                               if (responses != null)
+                                       for (final CompositeResponseObject cno : responses) {
+                                               this.addAll(cno.getCompositeAsList());
+                                       }
+                       }
+               });
+
+               if (responses == null || responses.isEmpty())
+                       throw new IllegalArgumentException("At least one CompositeResponseObject is mandatory.");
+               this.responses = responses;
+
+               if (svecList != null)
+                       this.svecList = svecList;
+               else
+                       this.svecList = Collections.emptyList();
+       }
+
+       /**
+        * Gets list of {@link CompositeResponseObject}.
+        *
+        * @return List<CompositeResponseObject>. Can't be null or empty.
+        */
+       public List<CompositeResponseObject> getResponses() {
+               return this.responses;
+       }
+
+       /**
+        * Gets list of {@link CompositeReplySvecObject}.
+        *
+        * @return List<CompositeReplySvecObject>. Can't be null but may be empty.
+        */
+       public List<CompositeReplySvecObject> getSvecList() {
+               return this.svecList;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.responses == null) ? 0 : this.responses.hashCode());
+               result = prime * result + ((this.svecList == null) ? 0 : this.svecList.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPReplyMessage other = (PCEPReplyMessage) obj;
+               if (this.responses == null) {
+                       if (other.responses != null)
+                               return false;
+               } else if (!this.responses.equals(other.responses))
+                       return false;
+               if (this.svecList == null) {
+                       if (other.svecList != null)
+                               return false;
+               } else if (!this.svecList.equals(other.svecList))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPReplyMessage [svecList=");
+               builder.append(this.svecList);
+               builder.append(", responses=");
+               builder.append(this.responses);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPReportMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPReportMessage.java
new file mode 100644 (file)
index 0000000..91f6bb4
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+
+/**
+ * Structure of Report Message
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-6.1">State
+ *      Report Message</a>
+ */
+public class PCEPReportMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = -3319055709351802748L;
+
+       private final List<CompositeStateReportObject> reports;
+
+       /**
+        * Constructs {@link PCEPReportMessage}.
+        *
+        * @throws IllegalArgumentException
+        *             if there is not even one {@link CompositeStateReportObject}
+        *             in the list.
+        *
+        * @param reports
+        *            List<CompositeStateReportObject>. Can't be empty or null.
+        */
+       public PCEPReportMessage(final List<CompositeStateReportObject> reports) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = 2785287687806615951L;
+
+                       {
+                               if (reports != null)
+                                       for (final CompositeStateReportObject csro : reports) {
+                                               this.addAll(csro.getCompositeAsList());
+                                       }
+                       }
+               });
+               if (reports == null || reports.isEmpty())
+                       throw new IllegalArgumentException("At least one CompositeStateReportObject is mandatory.");
+
+               this.reports = reports;
+       }
+
+       /**
+        * Gets list of {@link CompositeStateReportObject}.
+        *
+        * @return List<CompositeStateReportObject>. Can't be null or empty.
+        */
+       public List<CompositeStateReportObject> getStateReports() {
+               return this.reports;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.reports == null) ? 0 : this.reports.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPReportMessage other = (PCEPReportMessage) obj;
+               if (this.reports == null) {
+                       if (other.reports != null)
+                               return false;
+               } else if (!this.reports.equals(other.reports))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPReportMessage [reports=");
+               builder.append(this.reports);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPRequestMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPRequestMessage.java
new file mode 100644 (file)
index 0000000..edb944d
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestSvecObject;
+
+/**
+ * Structure of Request Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.4">Request
+ *      Message</a>
+ */
+public class PCEPRequestMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = -1914670070018415483L;
+
+       private final List<CompositeRequestSvecObject> svecList;
+
+       private final List<CompositeRequestObject> requests;
+
+       /**
+        * Constructs new Request Message.
+        *
+        * @throws IllegalArgumentException
+        *             if there is not even one {@link CompositeRequestObject} in
+        *             the list.
+        *
+        * @param requests
+        *            List<CompositeRequestObject>. Can't be empty or null.
+        */
+       public PCEPRequestMessage(final List<CompositeRequestObject> requests) {
+               this(null, requests);
+       }
+
+       /**
+        * Constructs new Request Message.
+        *
+        * @throws IllegalArgumentException
+        *             if there is not even one {@link CompositeRequestObject} in
+        *             the list.
+        *
+        * @param svecList
+        *            List<CompositeSvecObject>
+        * @param requests
+        *            List<CompositeRequestObject>. Can't be null or empty.
+        */
+       public PCEPRequestMessage(final List<CompositeRequestSvecObject> svecList, final List<CompositeRequestObject> requests) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = -6183368691183167076L;
+
+                       {
+                               if (svecList != null)
+                                       for (final CompositeRequestSvecObject cso : svecList) {
+                                               this.addAll(cso.getCompositeAsList());
+                                       }
+                               if (requests != null)
+                                       for (final CompositeRequestObject cro : requests) {
+                                               this.addAll(cro.getCompositeAsList());
+                                       }
+                       }
+               });
+               if (svecList != null)
+                       this.svecList = svecList;
+               else
+                       this.svecList = Collections.emptyList();
+
+               if (requests == null || requests.isEmpty())
+                       throw new IllegalArgumentException("At least one CompositeRequestObject is mandatory.");
+               this.requests = requests;
+
+       }
+
+       /**
+        * Gets list of {@link CompositeRequestSvecObject}.
+        *
+        * @return List<CompositeSvecObject>. Can't be null, but may be empty.
+        */
+       public List<CompositeRequestSvecObject> getSvecObjects() {
+               return this.svecList;
+       }
+
+       /**
+        * Gets list of {@link CompositeRequestObject}.
+        *
+        * @return List<CompositeRequestObject>. Can't be null or empty.
+        */
+       public List<CompositeRequestObject> getRequests() {
+               return this.requests;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.requests == null) ? 0 : this.requests.hashCode());
+               result = prime * result + ((this.svecList == null) ? 0 : this.svecList.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPRequestMessage other = (PCEPRequestMessage) obj;
+               if (this.requests == null) {
+                       if (other.requests != null)
+                               return false;
+               } else if (!this.requests.equals(other.requests))
+                       return false;
+               if (this.svecList == null) {
+                       if (other.svecList != null)
+                               return false;
+               } else if (!this.svecList.equals(other.svecList))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPRequestMessage [svecObjs=");
+               builder.append(this.svecList);
+               builder.append(", requests=");
+               builder.append(this.requests);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPUpdateRequestMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPUpdateRequestMessage.java
new file mode 100644 (file)
index 0000000..e477d11
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+
+/**
+ * Structure of Update Request Message.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-6.2">Update
+ *      Request Message</a>
+ */
+public class PCEPUpdateRequestMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = 3577204028363946097L;
+
+       private final List<CompositeUpdateRequestObject> updateRequests;
+
+       /**
+        * Constructs new Update Request Message.
+        *
+        * @throws IllegalArgumentException
+        *             if there is not even one {@link CompositeUpdateRequestObject}
+        *             in the list.
+        *
+        * @param updateRequests
+        *            List<CompositeUpdateRequestObject>. Can't be empty or null.
+        */
+       public PCEPUpdateRequestMessage(final List<CompositeUpdateRequestObject> updateRequests) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = 8591736379229064997L;
+
+                       {
+                               if (updateRequests != null)
+                                       for (final CompositeUpdateRequestObject curo : updateRequests) {
+                                               this.addAll(curo.getCompositeAsList());
+                                       }
+                       }
+               });
+
+               if (updateRequests == null || updateRequests.isEmpty())
+                       throw new IllegalArgumentException("At least one CompositeUpdateRequestObject is mandatory.");
+               this.updateRequests = updateRequests;
+       }
+
+       /**
+        * Gets list of {@link CompositeUpdateRequestObject}.
+        *
+        * @return List<CompositeUpdateRequestObject>. Can't be null or empty.
+        */
+       public List<CompositeUpdateRequestObject> getUpdateRequests() {
+               return this.updateRequests;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.updateRequests == null) ? 0 : this.updateRequests.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPUpdateRequestMessage other = (PCEPUpdateRequestMessage) obj;
+               if (this.updateRequests == null) {
+                       if (other.updateRequests != null)
+                               return false;
+               } else if (!this.updateRequests.equals(other.updateRequests))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPUpdateRequestMessage [updateRequests=");
+               builder.append(this.updateRequests);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPXRAddTunnelMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPXRAddTunnelMessage.java
new file mode 100644 (file)
index 0000000..62f09a4
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+
+/**
+ * Add tunnel message for interop with EnXR PCC.
+ */
+public class PCEPXRAddTunnelMessage extends PCEPMessage {
+
+       //private final PCEPRequestParameterObject requestParameter;
+
+       private static final long serialVersionUID = -5832314519461628024L;
+
+       private final PCEPLspObject lsp;
+
+       private final PCEPEndPointsObject<?> endPoints;
+
+       private final PCEPExplicitRouteObject ero;
+
+       public PCEPXRAddTunnelMessage(final PCEPLspObject lsp,
+                       final PCEPEndPointsObject<?> endPoints, final PCEPExplicitRouteObject ero) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = -1810245662746464028L;
+
+                       {
+                               //if (requestParameter != null)
+                               //      this.add(requestParameter);
+                               if (lsp != null)
+                                       this.add(lsp);
+                               if (endPoints != null)
+                                       this.add(endPoints);
+                               if (ero != null)
+                                       this.add(ero);
+                       }
+               });
+               if (lsp == null || endPoints == null || ero == null)
+                       throw new IllegalArgumentException("All objects are mandatory. Can't be null.");
+       //      this.requestParameter = requestParameter;
+               this.lsp = lsp;
+               this.endPoints = endPoints;
+               this.ero = ero;
+       }
+
+       /**
+        * @return the requestParameter
+        */
+//     public PCEPRequestParameterObject getRequestParameter() {
+//             return this.requestParameter;
+//     }
+
+       /**
+        * @return the lsp
+        */
+       public PCEPLspObject getLsp() {
+               return this.lsp;
+       }
+
+       /**
+        * @return the endPoints
+        */
+       public PCEPEndPointsObject<?> getEndPoints() {
+               return this.endPoints;
+       }
+
+       /**
+        * @return the ero
+        */
+       public PCEPExplicitRouteObject getEro() {
+               return this.ero;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result
+                               + ((this.endPoints == null) ? 0 : this.endPoints.hashCode());
+               result = prime * result + ((this.ero == null) ? 0 : this.ero.hashCode());
+               result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof PCEPXRAddTunnelMessage))
+                       return false;
+               final PCEPXRAddTunnelMessage other = (PCEPXRAddTunnelMessage) obj;
+               if (this.endPoints == null) {
+                       if (other.endPoints != null)
+                               return false;
+               } else if (!this.endPoints.equals(other.endPoints))
+                       return false;
+               if (this.ero == null) {
+                       if (other.ero != null)
+                               return false;
+               } else if (!this.ero.equals(other.ero))
+                       return false;
+               if (this.lsp == null) {
+                       if (other.lsp != null)
+                               return false;
+               } else if (!this.lsp.equals(other.lsp))
+                       return false;
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPXRAddTunnelMessage [lsp=");
+               builder.append(this.lsp);
+               builder.append(", endPoints=");
+               builder.append(this.endPoints);
+               builder.append(", ero=");
+               builder.append(this.ero);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPXRDeleteTunnelMessage.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/message/PCEPXRDeleteTunnelMessage.java
new file mode 100644 (file)
index 0000000..b6ded64
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.message;
+
+import java.util.ArrayList;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+
+/**
+ * Delete tunnel message for interop with EnXR PCC.
+ */
+public class PCEPXRDeleteTunnelMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = -8147187272108419351L;
+
+       private final PCEPLspObject lsp;
+
+       public PCEPXRDeleteTunnelMessage(final PCEPLspObject lsp) {
+               super(new ArrayList<PCEPObject>() {
+
+                       private static final long serialVersionUID = 3374457164202667362L;
+
+                       {
+                               if (lsp != null)
+                                       this.add(lsp);
+                       }
+               });
+               if (lsp == null)
+                       throw new IllegalArgumentException("All objects are mandatory. Can't be null.");
+               this.lsp = lsp;
+       }
+
+       /**
+        * @return the lsp
+        */
+       public PCEPLspObject getLsp() {
+               return this.lsp;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+               return result;
+       }
+
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (!(obj instanceof PCEPXRDeleteTunnelMessage))
+                       return false;
+               final PCEPXRDeleteTunnelMessage other = (PCEPXRDeleteTunnelMessage) obj;
+               if (this.lsp == null) {
+                       if (other.lsp != null)
+                               return false;
+               } else if (!this.lsp.equals(other.lsp))
+                       return false;
+               return true;
+       }
+
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPXRDeleteTunnelMessage [lsp=");
+               builder.append(this.lsp);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeErrorObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeErrorObject.java
new file mode 100644 (file)
index 0000000..e657b7b
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.7">Error (PCErr)
+ *      Message</a> - &lt;error&gt;
+ */
+public class CompositeErrorObject {
+
+       private List<PCEPRequestParameterObject> requestParameters;
+
+       private final List<PCEPErrorObject> errors;
+
+       public CompositeErrorObject(final PCEPRequestParameterObject requestParameter, final PCEPErrorObject error) {
+               this(new ArrayList<PCEPRequestParameterObject>() {
+                       private static final long serialVersionUID = -3974192068960284132L;
+
+                       {
+                               if (requestParameter != null)
+                                       this.add(requestParameter);
+                       }
+               }, new ArrayList<PCEPErrorObject>() {
+                       private static final long serialVersionUID = -3976331879683713909L;
+
+                       {
+                               if (error != null)
+                                       this.add(error);
+                       }
+               });
+       }
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        * 
+        * @param errors
+        *            List<PCEPErrorObject>. Can't be null or empty.
+        */
+       public CompositeErrorObject(List<PCEPErrorObject> errors) {
+               this(null, errors);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        * 
+        * @param requestParameters
+        *            List<PCEPRequestParameterObject>
+        * @param errors
+        *            List<PCEPErrorObject>. Can't be null or empty.
+        */
+       public CompositeErrorObject(List<PCEPRequestParameterObject> requestParameters, List<PCEPErrorObject> errors) {
+
+               if (errors == null || errors.isEmpty())
+                       throw new IllegalArgumentException("Error Object is mandatory.");
+               this.errors = errors;
+               if (requestParameters != null)
+                       this.requestParameters = requestParameters;
+               else
+                       this.requestParameters = Collections.emptyList();
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        * 
+        * @return List<PCEPObject>. Can't be null or empty.
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               if (this.requestParameters != null && !this.requestParameters.isEmpty())
+                       list.addAll(this.requestParameters);
+               list.addAll(this.errors);
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * 
+        * @param objects
+        *            List<PCEPObject> list of PCEPObjects from whose this object
+        *            should be created.
+        * @return CompositeErrorObject
+        */
+       public static CompositeErrorObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty())
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+
+               final List<PCEPRequestParameterObject> requestParameters = new ArrayList<PCEPRequestParameterObject>();
+               final List<PCEPErrorObject> errors = new ArrayList<PCEPErrorObject>();
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPRequestParameterObject) {
+                                               requestParameters.add((PCEPRequestParameterObject) obj);
+                                               state = 1;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPErrorObject) {
+                                               errors.add((PCEPErrorObject) obj);
+                                               state = 2;
+                                               break;
+                                       }
+                       }
+
+                       if (state == 3) {
+                               break;
+                       }
+
+                       objects.remove(obj);
+               }
+
+               if (errors.isEmpty())
+                       throw new IllegalArgumentException("Atleast one PCEPErrorObject is mandatory.");
+
+               return new CompositeErrorObject(requestParameters, errors);
+       }
+
+       /**
+        * Gets list of {@link PCEPRequestParameterObject}.
+        * 
+        * @return List<PCEPRequestParameterObject>. Can't be null, but may be
+        *         empty.
+        */
+       public List<PCEPRequestParameterObject> getRequestParameters() {
+               return this.requestParameters;
+       }
+
+       /**
+        * Gets list of {@link PCEPErrorObject}
+        * 
+        * @return List<PCEPErrorObject>. Can't be null or empty.
+        */
+       public List<PCEPErrorObject> getErrors() {
+               return this.errors;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.errors == null) ? 0 : this.errors.hashCode());
+               result = prime * result + ((this.requestParameters == null) ? 0 : this.requestParameters.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final CompositeErrorObject other = (CompositeErrorObject) obj;
+               if (this.errors == null) {
+                       if (other.errors != null)
+                               return false;
+               } else if (!this.errors.equals(other.errors))
+                       return false;
+               if (this.requestParameters == null) {
+                       if (other.requestParameters != null)
+                               return false;
+               } else if (!this.requestParameters.equals(other.requestParameters))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeErrorObject [requestParameters=");
+               builder.append(this.requestParameters);
+               builder.append(", errors=");
+               builder.append(this.errors);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeInstantiationObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeInstantiationObject.java
new file mode 100644 (file)
index 0000000..e2eb50e
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a href="http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt">PCCreate Message</a>
+ */
+public class CompositeInstantiationObject {
+
+       private final PCEPEndPointsObject<?> endPoints;
+
+       private final PCEPLspaObject lspa;
+
+       private final PCEPExplicitRouteObject ero;
+
+       private final PCEPRequestedPathBandwidthObject bandwidth;
+
+       private final List<PCEPMetricObject> metrics;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        *
+        * @param endPoints
+        *            PCEPEndPointsObject<?>. Can't be null.
+        * @param lspa
+        *            PCEPLspaObject. Can't be null.
+        */
+       public CompositeInstantiationObject(PCEPEndPointsObject<?> endPoints, PCEPLspaObject lspa) {
+               this(endPoints, lspa, null, null, null);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        *
+        * @param endPoints
+        *                      PCEPEndPointsObject<?>. Can't be null.
+        * @param lspa
+        *                      PCEPLspaObject. Can't be null.
+        * @param ero
+        *                      PCEPExplicitRouteObject
+        * @param bandwidth
+        *                      PCEPRequestedPathBandwidthObject
+        * @param metrics
+        *                      List<PCEPMetricObject>
+        */
+       public CompositeInstantiationObject(PCEPEndPointsObject<?> endPoints, PCEPLspaObject lspa, PCEPExplicitRouteObject ero, PCEPRequestedPathBandwidthObject bandwidth, List<PCEPMetricObject> metrics) {
+               this.endPoints = endPoints;
+               this.lspa = lspa;
+               this.ero = ero;
+               this.bandwidth = bandwidth;
+               this.metrics = metrics;
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        *
+        * @return List<PCEPObject>. Can't be null or empty.
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               list.add(this.endPoints);
+               list.add(this.lspa);
+               if (this.ero != null)
+                       list.add(this.ero);
+               if (this.bandwidth != null)
+                       list.add(this.bandwidth);
+               if (this.metrics != null && !this.metrics.isEmpty())
+                       list.addAll(this.metrics);
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        *
+        * @param objects
+        *            List<PCEPObject> list of PCEPObjects from whose this object
+        *            should be created.
+        * @return CompositeInstantiationObject
+        */
+       public static CompositeInstantiationObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+               }
+
+               PCEPEndPointsObject<?> endPoints = null;
+               if (objects.get(0) instanceof PCEPEndPointsObject<?>) {
+                       endPoints = (PCEPEndPointsObject<?>) objects.get(0);
+                       objects.remove(endPoints);
+               } else
+                       throw new IllegalArgumentException("End Points object must be first.");
+
+               PCEPLspaObject lspa = null;
+               if (objects.get(0) instanceof PCEPLspaObject) {
+                       lspa = (PCEPLspaObject) objects.get(0);
+                       objects.remove(lspa);
+               } else
+                       throw new IllegalArgumentException("LSPA object must be second.");
+
+               PCEPExplicitRouteObject ero = null;
+               PCEPRequestedPathBandwidthObject bandwidth = null;
+               final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPExplicitRouteObject) {
+                                               ero = (PCEPExplicitRouteObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                                               bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+                                               break;
+                                       }
+                               case 3:
+                                       state = 4;
+                                       if (obj instanceof PCEPMetricObject) {
+                                               metrics.add((PCEPMetricObject) obj);
+                                               state = 3;
+
+                                               break;
+                                       }
+                       }
+
+                       if (state == 4) {
+                               break;
+                       }
+
+                       objects.remove(obj);
+               }
+
+               return new CompositeInstantiationObject(endPoints, lspa, ero, bandwidth, metrics);
+       }
+
+       /**
+        * @return the endPoints
+        */
+       public final PCEPEndPointsObject<?> getEndPoints() {
+               return this.endPoints;
+       }
+
+       /**
+        * @return the lspa
+        */
+       public final PCEPLspaObject getLspa() {
+               return this.lspa;
+       }
+
+       /**
+        * @return the ero
+        */
+       public final PCEPExplicitRouteObject getEro() {
+               return this.ero;
+       }
+
+       /**
+        * @return the bandwidth
+        */
+       public final PCEPRequestedPathBandwidthObject getBandwidth() {
+               return this.bandwidth;
+       }
+
+       /**
+        * @return the metrics
+        */
+       public final List<PCEPMetricObject> getMetrics() {
+               return this.metrics;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result
+                               + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+               result = prime * result
+                               + ((this.endPoints == null) ? 0 : this.endPoints.hashCode());
+               result = prime * result + ((this.ero == null) ? 0 : this.ero.hashCode());
+               result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+               result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof CompositeInstantiationObject))
+                       return false;
+               final CompositeInstantiationObject other = (CompositeInstantiationObject) obj;
+               if (this.bandwidth == null) {
+                       if (other.bandwidth != null)
+                               return false;
+               } else if (!this.bandwidth.equals(other.bandwidth))
+                       return false;
+               if (this.endPoints == null) {
+                       if (other.endPoints != null)
+                               return false;
+               } else if (!this.endPoints.equals(other.endPoints))
+                       return false;
+               if (this.ero == null) {
+                       if (other.ero != null)
+                               return false;
+               } else if (!this.ero.equals(other.ero))
+                       return false;
+               if (this.lspa == null) {
+                       if (other.lspa != null)
+                               return false;
+               } else if (!this.lspa.equals(other.lspa))
+                       return false;
+               if (this.metrics == null) {
+                       if (other.metrics != null)
+                               return false;
+               } else if (!this.metrics.equals(other.metrics))
+                       return false;
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeInstantiationObject [endPoints=");
+               builder.append(this.endPoints);
+               builder.append(", lspa=");
+               builder.append(this.lspa);
+               builder.append(", ero=");
+               builder.append(this.ero);
+               builder.append(", bandwidth=");
+               builder.append(this.bandwidth);
+               builder.append(", metrics=");
+               builder.append(this.metrics);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeNotifyObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeNotifyObject.java
new file mode 100644 (file)
index 0000000..6e9ebd5
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.6">Notification
+ *      (PCNtf) Message</a> - &lt;notify&gt;
+ */
+public class CompositeNotifyObject {
+
+       private List<PCEPRequestParameterObject> requestParameters;
+
+       private final List<PCEPNotificationObject> notifications;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        *
+        * @param notifications
+        *            List<PCEPNotificationObject>. Can't be null or empty.
+        */
+       public CompositeNotifyObject(List<PCEPNotificationObject> notifications) {
+               this(null, notifications);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        *
+        * @param requestParameters
+        *            List<PCEPRequestParameterObject>
+        * @param notifications
+        *            List<PCEPNotificationObject>. Can't be null or empty.
+        */
+       public CompositeNotifyObject(List<PCEPRequestParameterObject> requestParameters, List<PCEPNotificationObject> notifications) {
+               if (notifications == null || notifications.isEmpty())
+                       throw new IllegalArgumentException("Notification Object is mandatory.");
+               if (requestParameters != null)
+                       this.requestParameters = requestParameters;
+               else
+                       this.requestParameters = Collections.emptyList();
+               this.notifications = notifications;
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        *
+        * @return List<PCEPObject>
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               if (this.requestParameters != null && !this.requestParameters.isEmpty())
+                       list.addAll(this.requestParameters);
+               list.addAll(this.notifications);
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * @param objects List<PCEPObject> list of PCEPObjects from whose this
+        * object should be created.
+        * @return CompositeNotifyObject
+        */
+       public static CompositeNotifyObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty())
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+
+               final List<PCEPRequestParameterObject> requestParameters = new ArrayList<PCEPRequestParameterObject>();
+               final List<PCEPNotificationObject> notifications = new ArrayList<PCEPNotificationObject>();
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPRequestParameterObject) {
+                                               requestParameters.add((PCEPRequestParameterObject) obj);
+                                               state = 1;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPNotificationObject) {
+                                               notifications.add((PCEPNotificationObject) obj);
+                                               state = 2;
+                                               break;
+                                       }
+                       }
+
+                       if (state == 3) {
+                               break;
+                       }
+
+                       objects.remove(obj);
+               }
+
+               if (notifications.isEmpty())
+                       return null;
+
+               return new CompositeNotifyObject(requestParameters, notifications);
+       }
+
+       /**
+        * Gets list of {@link PCEPRequestParameterObject}.
+        *
+        * @return List<PCEPRequestParameterObject>. Can't be null, but may be
+        *         empty.
+        */
+       public List<PCEPRequestParameterObject> getRequestParameters() {
+               return this.requestParameters;
+       }
+
+       /**
+        * Gets list of {@link PCEPNotificationObject}.
+        *
+        * @return List<PCEPNotificationObject>. Can't be null or empty.
+        */
+       public List<PCEPNotificationObject> getNotificationObjects() {
+               return this.notifications;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.notifications == null) ? 0 : this.notifications.hashCode());
+               result = prime * result + ((this.requestParameters == null) ? 0 : this.requestParameters.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final CompositeNotifyObject other = (CompositeNotifyObject) obj;
+               if (this.notifications == null) {
+                       if (other.notifications != null)
+                               return false;
+               } else if (!this.notifications.equals(other.notifications))
+                       return false;
+               if (this.requestParameters == null) {
+                       if (other.requestParameters != null)
+                               return false;
+               } else if (!this.requestParameters.equals(other.requestParameters))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeNotifyObject [requestParameters=");
+               builder.append(this.requestParameters);
+               builder.append(", notifications=");
+               builder.append(this.notifications);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositePathObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositePathObject.java
new file mode 100644 (file)
index 0000000..0c00cae
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.5">Path
+ *      Computation Reply (PCRep) Message</a> - &lt;path&gt;</br> Same for every
+ *      usage of path object.
+ */
+public class CompositePathObject {
+
+       private final PCEPExplicitRouteObject explicitRoute;
+
+       private final PCEPLspaObject lspa;
+
+       private final PCEPRequestedPathBandwidthObject bandwidth;
+
+       private List<PCEPMetricObject> metrics;
+
+       private final PCEPIncludeRouteObject includeRoute;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        *
+        * @param explicitRoute
+        *            PCEPExplicitRouteObject. Can't be null or empty.
+        */
+       public CompositePathObject(PCEPExplicitRouteObject explicitRoute) {
+               this(explicitRoute, null, null, null, null);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        *
+        * @param explicitRoute
+        *            PCEPExplicitRouteObject. Can't be null or empty.
+        * @param lspa
+        *            PCEPLspaObject
+        * @param bandwidth
+        *            PCEPRequestedPathBandwidthObject
+        * @param metrics
+        *            List<PCEPMetricObject>
+        * @param includeRoute
+        *            PCEPIncludeRouteObject
+        */
+       public CompositePathObject(PCEPExplicitRouteObject explicitRoute, PCEPLspaObject lspa, PCEPRequestedPathBandwidthObject bandwidth,
+                       List<PCEPMetricObject> metrics, PCEPIncludeRouteObject includeRoute) {
+               if (explicitRoute == null)
+                       throw new IllegalArgumentException("Explicit Route Object is mandatory.");
+               this.explicitRoute = explicitRoute;
+               this.lspa = lspa;
+               this.bandwidth = bandwidth;
+               if (metrics != null)
+                       this.metrics = metrics;
+               else
+                       this.metrics = Collections.emptyList();
+               this.includeRoute = includeRoute;
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        *
+        * @return List<PCEPObject>. Can't be null or empty.
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               list.add(this.explicitRoute);
+               if (this.lspa != null)
+                       list.add(this.lspa);
+               if (this.bandwidth != null)
+                       list.add(this.bandwidth);
+               if (this.metrics != null && !this.metrics.isEmpty())
+                       list.addAll(this.metrics);
+               if (this.includeRoute != null)
+                       list.add(this.includeRoute);
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * @param objects List<PCEPObject> list of PCEPObjects from whose this
+        * object should be created.
+        * @return CompositePathObject
+        */
+       public static CompositePathObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+               }
+
+               PCEPExplicitRouteObject explicitRoute = null;
+               if (objects.get(0) instanceof PCEPExplicitRouteObject) {
+                       explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+                       objects.remove(explicitRoute);
+               } else
+                       return null;
+
+               PCEPLspaObject lspa = null;
+               PCEPRequestedPathBandwidthObject bandwidth = null;
+               final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+               PCEPIncludeRouteObject iro = null;
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPLspaObject) {
+                                               lspa = (PCEPLspaObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                                               bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+                                               break;
+                                       }
+                               case 3:
+                                       if (obj instanceof PCEPMetricObject) {
+                                               metrics.add((PCEPMetricObject) obj);
+                                               state = 3;
+                                               break;
+                                       } else
+                                               state = 4;
+                               case 4:
+                                       if (obj instanceof PCEPIncludeRouteObject) {
+                                               iro = (PCEPIncludeRouteObject) obj;
+                                               break;
+                                       }
+                                       state = 5;
+                       }
+
+                       if (state == 5) {
+                               break;
+                       }
+
+                       objects.remove(obj);
+               }
+
+               return new CompositePathObject(explicitRoute, lspa, bandwidth, metrics, iro);
+       }
+
+       /**
+        * Gets {@link PCEPExplicitRouteObject}.
+        *
+        * @return PCEPExplicitRouteObject. Can't be null.
+        */
+       public PCEPExplicitRouteObject getExcludedRoute() {
+               return this.explicitRoute;
+       }
+
+       /**
+        * Gets {@link PCEPLspaObject}.
+        *
+        * @return PCEPLspaObject. May be null.
+        */
+       public PCEPLspaObject getLspa() {
+               return this.lspa;
+       }
+
+       /**
+        * Gets {@link PCEPBandwidthObject}.
+        *
+        * @return PCEPBandwidthObject. May be null.
+        */
+       public PCEPBandwidthObject getBandwidth() {
+               return this.bandwidth;
+       }
+
+       /**
+        * Gets list of {@link PCEPMetricObject}.
+        *
+        * @return List<PCEPMetricObject>. Can't be null, but may be empty.
+        */
+       public List<PCEPMetricObject> getMetrics() {
+               return this.metrics;
+       }
+
+       /**
+        * Gets {@link PCEPIncludeRouteObject}.
+        *
+        * @return PCEPIncludeRouteObject. May be null.
+        */
+       public PCEPIncludeRouteObject getIncludeRoute() {
+               return this.includeRoute;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+               result = prime * result + ((this.explicitRoute == null) ? 0 : this.explicitRoute.hashCode());
+               result = prime * result + ((this.includeRoute == null) ? 0 : this.includeRoute.hashCode());
+               result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+               result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final CompositePathObject other = (CompositePathObject) obj;
+               if (this.bandwidth == null) {
+                       if (other.bandwidth != null)
+                               return false;
+               } else if (!this.bandwidth.equals(other.bandwidth))
+                       return false;
+               if (this.explicitRoute == null) {
+                       if (other.explicitRoute != null)
+                               return false;
+               } else if (!this.explicitRoute.equals(other.explicitRoute))
+                       return false;
+               if (this.includeRoute == null) {
+                       if (other.includeRoute != null)
+                               return false;
+               } else if (!this.includeRoute.equals(other.includeRoute))
+                       return false;
+               if (this.lspa == null) {
+                       if (other.lspa != null)
+                               return false;
+               } else if (!this.lspa.equals(other.lspa))
+                       return false;
+               if (this.metrics == null) {
+                       if (other.metrics != null)
+                               return false;
+               } else if (!this.metrics.equals(other.metrics))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositePathObject [explicitRoute=");
+               builder.append(this.explicitRoute);
+               builder.append(", lspa=");
+               builder.append(this.lspa);
+               builder.append(", bandwidth=");
+               builder.append(this.bandwidth);
+               builder.append(", metrics=");
+               builder.append(this.metrics);
+               builder.append(", includeRoute=");
+               builder.append(this.includeRoute);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeReplySvecObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeReplySvecObject.java
new file mode 100644 (file)
index 0000000..41d4c7f
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+
+/**
+ * Composite SvecObject used in {@link PCEPReplyMessage}
+ */
+public class CompositeReplySvecObject {
+
+       private final PCEPSvecObject svec;
+       private final PCEPObjectiveFunctionObject objectiveFunction;
+       private final List<PCEPMetricObject> metrics;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        * 
+        * @param svec
+        *            PCEPSvecObject
+        */
+       public CompositeReplySvecObject(PCEPSvecObject svec) {
+               this(svec, null, null);
+       }
+
+       /**
+        * Constructs composite object also with optional objects.
+        * 
+        * @param svec
+        *            PCEPSvecObject
+        * @param objectiveFunction
+        *            PCEPObjectiveFunctionObject
+        * @param metrics
+        *            list of PCEPMetricObject
+        */
+       public CompositeReplySvecObject(PCEPSvecObject svec, PCEPObjectiveFunctionObject objectiveFunction, List<PCEPMetricObject> metrics) {
+               if (svec == null)
+                       throw new IllegalArgumentException("Svec object is mandatory.");
+               this.svec = svec;
+               this.objectiveFunction = objectiveFunction;
+               if (metrics != null)
+                       this.metrics = metrics;
+               else
+                       this.metrics = Collections.emptyList();
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        * 
+        * @return List<PCEPObject>. Can't be null or empty.
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               list.add(this.svec);
+               if (this.objectiveFunction != null)
+                       list.add(this.objectiveFunction);
+               if (this.metrics != null && !this.metrics.isEmpty())
+                       list.addAll(this.metrics);
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * 
+        * @param objects
+        *            List<PCEPObject> list of PCEPObjects from whose this object
+        *            should be created.
+        * @return CompositePathObject
+        */
+       public static CompositeReplySvecObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+               }
+
+               PCEPSvecObject svec = null;
+               if (objects.get(0) instanceof PCEPSvecObject) {
+                       svec = (PCEPSvecObject) objects.get(0);
+                       objects.remove(svec);
+               } else
+                       return null;
+
+               PCEPObjectiveFunctionObject of = null;
+               final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPObjectiveFunctionObject) {
+                                               of = (PCEPObjectiveFunctionObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPMetricObject) {
+                                               metrics.add((PCEPMetricObject) obj);
+                                               state = 2;
+
+                                               break;
+                                       }
+                       }
+
+                       if (state == 3)
+                               break;
+
+                       objects.remove(obj);
+               }
+
+               return new CompositeReplySvecObject(svec, of, metrics);
+       }
+
+       /**
+        * Gets {@link PCEPSvecObject}
+        * 
+        * @return PCEPSvecObject. Can't be null.
+        */
+       public PCEPSvecObject getSvec() {
+               return this.svec;
+       }
+
+       /**
+        * Gets {@link PCEPObjectiveFunctionObject}
+        * 
+        * @return PCEPObjectiveFunctionObject. May be null.
+        */
+       public PCEPObjectiveFunctionObject getObjectiveFunction() {
+               return this.objectiveFunction;
+       }
+
+       /**
+        * @return the metrics
+        */
+       public List<PCEPMetricObject> getMetrics() {
+               return this.metrics;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeReplySvecObject [svec=");
+               builder.append(this.svec);
+               builder.append(", objectiveFunction=");
+               builder.append(this.objectiveFunction);
+               builder.append(", metrics=");
+               builder.append(this.metrics);
+               builder.append("]");
+               return builder.toString();
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+               result = prime * result + ((this.objectiveFunction == null) ? 0 : this.objectiveFunction.hashCode());
+               result = prime * result + ((this.svec == null) ? 0 : this.svec.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final CompositeReplySvecObject other = (CompositeReplySvecObject) obj;
+               if (this.metrics == null) {
+                       if (other.metrics != null)
+                               return false;
+               } else if (!this.metrics.equals(other.metrics))
+                       return false;
+               if (this.objectiveFunction == null) {
+                       if (other.objectiveFunction != null)
+                               return false;
+               } else if (!this.objectiveFunction.equals(other.objectiveFunction))
+                       return false;
+               if (this.svec == null) {
+                       if (other.svec != null)
+                               return false;
+               } else if (!this.svec.equals(other.svec))
+                       return false;
+               return true;
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeRequestObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeRequestObject.java
new file mode 100644 (file)
index 0000000..392c5a3
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.4">Path
+ *      Computation Request (PCReq) Message</a> - &lt;request&gt;</br>
+ * 
+ * @see <a href="tools.ietf.org/html/rfc5455#section-3.2">Path Computation
+ *      Request Message with CLASSTYPE Object</a>
+ */
+public class CompositeRequestObject {
+
+       private final PCEPRequestParameterObject requestParameter;
+
+       private final PCEPEndPointsObject<?> endPoints;
+
+       private final PCEPClassTypeObject classType;
+
+       private final PCEPLspObject lsp;
+
+       private final PCEPLspaObject lspa;
+
+       private final PCEPRequestedPathBandwidthObject bandwidth;
+
+       private final List<PCEPMetricObject> metrics;
+
+       private final PCEPReportedRouteObject reportedRoute;
+
+       private final PCEPExistingPathBandwidthObject rroBandwidth;
+
+       private final PCEPIncludeRouteObject includeRoute;
+
+       private final PCEPLoadBalancingObject loadBalancing;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        * 
+        * @param requestParameter
+        *            PCEPRequestParameterObject. Can't be null.
+        * @param endPoints
+        *            PCEPEndPointsObject<?>. Can't be null.
+        */
+       public CompositeRequestObject(PCEPRequestParameterObject requestParameter, PCEPEndPointsObject<?> endPoints) {
+               this(requestParameter, endPoints, null, null, null, null, null, null, null, null, null);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        * 
+        * @param requestParameter
+        *            PCEPRequestParameterObject. Can't be null.
+        * @param endPoints
+        *            PCEPEndPointsObject<?>. Can't be null.
+        * @param classType
+        *            PCEPClassTypeObject
+        * @param lsp
+        *            PCEPLspObject
+        * @param lspa
+        *            PCEPLspaObject
+        * @param bandwidth
+        *            PCEPRequestedPathBandwidthObject
+        * @param metrics
+        *            List<PCEPMetricObject>
+        * @param reportedRoute
+        *            PCEPReportedRouteObject
+        * @param rroBandwidth
+        *            PCEPExistingPathBandwidthObject
+        * @param includeRoute
+        *            PCEPIncludeRouteObject
+        * @param loadBalancing
+        *            PCEPLoadBalancingObject
+        */
+       public CompositeRequestObject(PCEPRequestParameterObject requestParameter, PCEPEndPointsObject<?> endPoints, PCEPClassTypeObject classType,
+                       PCEPLspObject lsp, PCEPLspaObject lspa, PCEPRequestedPathBandwidthObject bandwidth, List<PCEPMetricObject> metrics,
+                       PCEPReportedRouteObject reportedRoute, PCEPExistingPathBandwidthObject rroBandwidth, PCEPIncludeRouteObject includeRoute,
+                       PCEPLoadBalancingObject loadBalancing) {
+               if (requestParameter == null)
+                       throw new IllegalArgumentException("Request Parameter Object is mandatory.");
+               if (endPoints == null)
+                       throw new IllegalArgumentException("End-Points Object is mandatory.");
+               this.requestParameter = requestParameter;
+               this.endPoints = endPoints;
+               this.classType = classType;
+               this.lsp = lsp;
+               this.lspa = lspa;
+               this.bandwidth = bandwidth;
+               if (metrics != null)
+                       this.metrics = metrics;
+               else
+                       this.metrics = Collections.emptyList();
+               this.reportedRoute = reportedRoute;
+               this.rroBandwidth = rroBandwidth;
+               this.includeRoute = includeRoute;
+               this.loadBalancing = loadBalancing;
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        * 
+        * @return List<PCEPObject>. Can't be null or empty.
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               list.add(this.requestParameter);
+               list.add(this.endPoints);
+               if (this.classType != null)
+                       list.add(this.classType);
+               if (this.lsp != null)
+                       list.add(this.lsp);
+               if (this.lspa != null)
+                       list.add(this.lspa);
+               if (this.bandwidth != null)
+                       list.add(this.bandwidth);
+               if (this.metrics != null && !this.metrics.isEmpty())
+                       list.addAll(this.metrics);
+               if (this.reportedRoute != null) {
+                       list.add(this.reportedRoute);
+                       if (this.rroBandwidth != null)
+                               list.add(this.rroBandwidth);
+               }
+               if (this.includeRoute != null)
+                       list.add(this.includeRoute);
+               if (this.loadBalancing != null)
+                       list.add(this.loadBalancing);
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * 
+        * @param objects
+        *            List<PCEPObject> list of PCEPObjects from whose this object
+        *            should be created.
+        * @return CompositeRequestObject
+        */
+       public static CompositeRequestObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+               }
+               PCEPRequestParameterObject requestParameter = null;
+               if (objects.get(0) instanceof PCEPRequestParameterObject) {
+                       requestParameter = (PCEPRequestParameterObject) objects.get(0);
+                       objects.remove(requestParameter);
+               } else
+                       return null;
+
+               PCEPEndPointsObject<?> endPoints = null;
+               if (objects.get(0) instanceof PCEPEndPointsObject<?>) {
+                       endPoints = (PCEPEndPointsObject<?>) objects.get(0);
+                       objects.remove(endPoints);
+               } else
+                       throw new IllegalArgumentException("End Points object must be second.");
+
+               PCEPClassTypeObject classType = null;
+               PCEPLspObject lsp = null;
+               PCEPLspaObject lspa = null;
+               PCEPRequestedPathBandwidthObject bandwidth = null;
+               final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+               PCEPReportedRouteObject rro = null;
+               PCEPExistingPathBandwidthObject rroBandwidth = null;
+               PCEPIncludeRouteObject iro = null;
+               PCEPLoadBalancingObject loadBalancing = null;
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPClassTypeObject) {
+                                               classType = (PCEPClassTypeObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPLspObject) {
+                                               lsp = (PCEPLspObject) obj;
+                                               break;
+                                       }
+                               case 3:
+                                       state = 4;
+                                       if (obj instanceof PCEPLspaObject) {
+                                               lspa = (PCEPLspaObject) obj;
+                                               break;
+                                       }
+                               case 4:
+                                       state = 5;
+                                       if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                                               bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+                                               break;
+                                       }
+                               case 5:
+                                       state = 6;
+                                       if (obj instanceof PCEPMetricObject) {
+                                               metrics.add((PCEPMetricObject) obj);
+                                               state = 5;
+
+                                               break;
+                                       }
+                               case 6:
+                                       state = 8;
+                                       if (obj instanceof PCEPReportedRouteObject) {
+                                               rro = (PCEPReportedRouteObject) obj;
+                                               state = 7;
+                                               break;
+                                       }
+                               case 7:
+                                       state = 8;
+                                       if (obj instanceof PCEPExistingPathBandwidthObject) {
+                                               rroBandwidth = (PCEPExistingPathBandwidthObject) obj;
+                                               break;
+                                       }
+                               case 8:
+                                       state = 9;
+                                       if (obj instanceof PCEPIncludeRouteObject) {
+                                               iro = (PCEPIncludeRouteObject) obj;
+                                               break;
+                                       }
+                               case 9:
+                                       if (obj instanceof PCEPLoadBalancingObject) {
+                                               loadBalancing = (PCEPLoadBalancingObject) obj;
+                                               break;
+                                       }
+                                       state = 10;
+                       }
+
+                       if (state == 10) {
+                               break;
+                       }
+
+                       objects.remove(obj);
+               }
+
+               return new CompositeRequestObject(requestParameter, endPoints, classType, lsp, lspa, bandwidth, metrics, rro, rroBandwidth, iro, loadBalancing);
+       }
+
+       /**
+        * Gets {@link PCEPRequestParameterObject}.
+        * 
+        * @return PCEPRequestParameterObject. Can't be null.
+        */
+       public PCEPRequestParameterObject getRequestParameter() {
+               return this.requestParameter;
+       }
+
+       /**
+        * Gets {@link PCEPEndPointsObject}.
+        * 
+        * @return PCEPEndPointsObject<?>. Can't be null.
+        */
+       public PCEPEndPointsObject<?> getEndPoints() {
+               return this.endPoints;
+       }
+
+       /**
+        * Gets {@link PCEPClassTypeObject}.
+        * 
+        * @return PCEPClassTypeObject. May be null.
+        */
+       public PCEPClassTypeObject getClassType() {
+               return this.classType;
+       }
+
+       /**
+        * Gets {@link PCEPLspObject}.
+        * 
+        * @return PCEPLspObject. May be null.
+        */
+       public PCEPLspObject getLsp() {
+               return this.lsp;
+       }
+
+       /**
+        * Gets {@link PCEPLspaObject}.
+        * 
+        * @return PCEPLspaObject. May be null.
+        */
+       public PCEPLspaObject getLspa() {
+               return this.lspa;
+       }
+
+       /**
+        * Gets {@link PCEPBandwidthObject}.
+        * 
+        * @return PCEPBandwidthObject. May be null.
+        */
+       public PCEPBandwidthObject getBandwidth() {
+               return this.bandwidth;
+       }
+
+       /**
+        * Gets list of {@link PCEPMetricObject}.
+        * 
+        * @return List<PCEPMetricObject>
+        */
+       public List<PCEPMetricObject> getMetrics() {
+               return this.metrics;
+       }
+
+       /**
+        * Gets {@link PCEPReportedRouteObject}.
+        * 
+        * @return PCEPReportedRouteObject. May be null.
+        */
+       public PCEPReportedRouteObject getReportedRoute() {
+               return this.reportedRoute;
+       }
+
+       /**
+        * Gets {@link PCEPBandwidthObject}.
+        * 
+        * @return PCEPBandwidthObject. May be null.
+        */
+       public PCEPBandwidthObject getRroBandwidth() {
+               return this.rroBandwidth;
+       }
+
+       /**
+        * Gets {@link PCEPIncludeRouteObject}.
+        * 
+        * @return PCEPIncludeRouteObject. May be null.
+        */
+       public PCEPIncludeRouteObject getIncludeRoute() {
+               return this.includeRoute;
+       }
+
+       /**
+        * Gets {@link PCEPLoadBalancingObject}.
+        * 
+        * @return PCEPLoadBalancingObject. May be null.
+        */
+       public PCEPLoadBalancingObject getLoadBalancing() {
+               return this.loadBalancing;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+               result = prime * result + ((this.classType == null) ? 0 : this.classType.hashCode());
+               result = prime * result + ((this.endPoints == null) ? 0 : this.endPoints.hashCode());
+               result = prime * result + ((this.includeRoute == null) ? 0 : this.includeRoute.hashCode());
+               result = prime * result + ((this.loadBalancing == null) ? 0 : this.loadBalancing.hashCode());
+               result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+               result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+               result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+               result = prime * result + ((this.reportedRoute == null) ? 0 : this.reportedRoute.hashCode());
+               result = prime * result + ((this.requestParameter == null) ? 0 : this.requestParameter.hashCode());
+               result = prime * result + ((this.rroBandwidth == null) ? 0 : this.rroBandwidth.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof CompositeRequestObject))
+                       return false;
+               final CompositeRequestObject other = (CompositeRequestObject) obj;
+               if (this.bandwidth == null) {
+                       if (other.bandwidth != null)
+                               return false;
+               } else if (!this.bandwidth.equals(other.bandwidth))
+                       return false;
+               if (this.classType == null) {
+                       if (other.classType != null)
+                               return false;
+               } else if (!this.classType.equals(other.classType))
+                       return false;
+               if (this.endPoints == null) {
+                       if (other.endPoints != null)
+                               return false;
+               } else if (!this.endPoints.equals(other.endPoints))
+                       return false;
+               if (this.includeRoute == null) {
+                       if (other.includeRoute != null)
+                               return false;
+               } else if (!this.includeRoute.equals(other.includeRoute))
+                       return false;
+               if (this.loadBalancing == null) {
+                       if (other.loadBalancing != null)
+                               return false;
+               } else if (!this.loadBalancing.equals(other.loadBalancing))
+                       return false;
+               if (this.lsp == null) {
+                       if (other.lsp != null)
+                               return false;
+               } else if (!this.lsp.equals(other.lsp))
+                       return false;
+               if (this.lspa == null) {
+                       if (other.lspa != null)
+                               return false;
+               } else if (!this.lspa.equals(other.lspa))
+                       return false;
+               if (this.metrics == null) {
+                       if (other.metrics != null)
+                               return false;
+               } else if (!this.metrics.equals(other.metrics))
+                       return false;
+               if (this.reportedRoute == null) {
+                       if (other.reportedRoute != null)
+                               return false;
+               } else if (!this.reportedRoute.equals(other.reportedRoute))
+                       return false;
+               if (this.requestParameter == null) {
+                       if (other.requestParameter != null)
+                               return false;
+               } else if (!this.requestParameter.equals(other.requestParameter))
+                       return false;
+               if (this.rroBandwidth == null) {
+                       if (other.rroBandwidth != null)
+                               return false;
+               } else if (!this.rroBandwidth.equals(other.rroBandwidth))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeRequestObject [requestParameter=");
+               builder.append(this.requestParameter);
+               builder.append(", endPoints=");
+               builder.append(this.endPoints);
+               builder.append(", classType=");
+               builder.append(this.classType);
+               builder.append(", lsp=");
+               builder.append(this.lsp);
+               builder.append(", lspa=");
+               builder.append(this.lspa);
+               builder.append(", bandwidth=");
+               builder.append(this.bandwidth);
+               builder.append(", metrics=");
+               builder.append(this.metrics);
+               builder.append(", reportedRoute=");
+               builder.append(this.reportedRoute);
+               builder.append(", rroBandwidth=");
+               builder.append(this.rroBandwidth);
+               builder.append(", includeRoute=");
+               builder.append(this.includeRoute);
+               builder.append(", loadBalancing=");
+               builder.append(this.loadBalancing);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeRequestSvecObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeRequestSvecObject.java
new file mode 100644 (file)
index 0000000..fc34817
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+
+/**
+ * Composite SvecObject used in {@link PCEPRequestMessage}
+ */
+public class CompositeRequestSvecObject {
+
+       private final PCEPSvecObject svec;
+       private final PCEPObjectiveFunctionObject objectiveFunction;
+       private final PCEPGlobalConstraintsObject globalConstraints;
+       private final PCEPExcludeRouteObject excludeRoute;
+       private final List<PCEPMetricObject> metrics;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        * 
+        * @param svec
+        *            PCEPSvecObject
+        */
+       public CompositeRequestSvecObject(PCEPSvecObject svec) {
+               this(svec, null, null, null, null);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        * 
+        * @param svec
+        *            PCEPSvecObject
+        * @param objectiveFunction
+        *            PCEPObjectiveFunctionObject
+        * @param globalConstraints
+        *            PCEPGlobalConstraints
+        * @param excludeRoute
+        *            PCEPExcludeRouteObject
+        * @param metrics
+        *            list of PCEPMetricObject
+        */
+       public CompositeRequestSvecObject(PCEPSvecObject svec, PCEPObjectiveFunctionObject objectiveFunction, PCEPGlobalConstraintsObject globalConstraints,
+                       PCEPExcludeRouteObject excludeRoute, List<PCEPMetricObject> metrics) {
+               if (svec == null)
+                       throw new IllegalArgumentException("Svec object is mandatory.");
+               this.svec = svec;
+               this.objectiveFunction = objectiveFunction;
+               this.globalConstraints = globalConstraints;
+               this.excludeRoute = excludeRoute;
+               if (metrics != null)
+                       this.metrics = metrics;
+               else
+                       this.metrics = Collections.emptyList();
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        * 
+        * @return List<PCEPObject>. Can't be null or empty.
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               list.add(this.svec);
+               if (this.objectiveFunction != null)
+                       list.add(this.objectiveFunction);
+               if (this.globalConstraints != null)
+                       list.add(this.globalConstraints);
+               if (this.excludeRoute != null)
+                       list.add(this.excludeRoute);
+               if (this.metrics != null && !this.metrics.isEmpty())
+                       list.addAll(this.metrics);
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * 
+        * @param objects
+        *            List<PCEPObject> list of PCEPObjects from whose this object
+        *            should be created.
+        * @return CompositePathObject
+        */
+       public static CompositeRequestSvecObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+               }
+
+               PCEPSvecObject svec = null;
+               if (objects.get(0) instanceof PCEPSvecObject) {
+                       svec = (PCEPSvecObject) objects.get(0);
+                       objects.remove(svec);
+               } else
+                       return null;
+
+               PCEPObjectiveFunctionObject of = null;
+               PCEPGlobalConstraintsObject gc = null;
+               PCEPExcludeRouteObject xro = null;
+               final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPObjectiveFunctionObject) {
+                                               of = (PCEPObjectiveFunctionObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPGlobalConstraintsObject) {
+                                               gc = (PCEPGlobalConstraintsObject) obj;
+                                               break;
+                                       }
+                               case 3:
+                                       state = 4;
+                                       if (obj instanceof PCEPExcludeRouteObject) {
+                                               xro = (PCEPExcludeRouteObject) obj;
+                                               break;
+                                       }
+                               case 4:
+                                       state = 5;
+                                       if (obj instanceof PCEPMetricObject) {
+                                               metrics.add((PCEPMetricObject) obj);
+                                               state = 4;
+
+                                               break;
+                                       }
+                       }
+
+                       if (state == 5)
+                               break;
+
+                       objects.remove(obj);
+               }
+
+               return new CompositeRequestSvecObject(svec, of, gc, xro, metrics);
+       }
+
+       /**
+        * Gets {@link PCEPSvecObject}
+        * 
+        * @return PCEPSvecObject. Can't be null.
+        */
+       public PCEPSvecObject getSvec() {
+               return this.svec;
+       }
+
+       /**
+        * Gets {@link PCEPObjectiveFunctionObject}
+        * 
+        * @return PCEPObjectiveFunctionObject. May be null.
+        */
+       public PCEPObjectiveFunctionObject getObjectiveFunction() {
+               return this.objectiveFunction;
+       }
+
+       /**
+        * Gets {@link PCEPGlobalConstraintsObject}
+        * 
+        * @return PCEPGlobalConstraints. May be null.
+        */
+       public PCEPGlobalConstraintsObject getGlobalConstraints() {
+               return this.globalConstraints;
+       }
+
+       /**
+        * Gets {@link PCEPExcludeRouteObject}
+        * 
+        * @return PCEPExcludeRouteObject. May be null.
+        */
+       public PCEPExcludeRouteObject getExcludeRoute() {
+               return this.excludeRoute;
+       }
+
+       /**
+        * @return the metrics
+        */
+       public List<PCEPMetricObject> getMetrics() {
+               return this.metrics;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeSvecObject [svec=");
+               builder.append(this.svec);
+               builder.append(", objectiveFunction=");
+               builder.append(this.objectiveFunction);
+               builder.append(", globalConstraints=");
+               builder.append(this.globalConstraints);
+               builder.append(", excludeRoute=");
+               builder.append(this.excludeRoute);
+               builder.append(", metrics=");
+               builder.append(this.metrics);
+               builder.append("]");
+               return builder.toString();
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.excludeRoute == null) ? 0 : this.excludeRoute.hashCode());
+               result = prime * result + ((this.globalConstraints == null) ? 0 : this.globalConstraints.hashCode());
+               result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+               result = prime * result + ((this.objectiveFunction == null) ? 0 : this.objectiveFunction.hashCode());
+               result = prime * result + ((this.svec == null) ? 0 : this.svec.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final CompositeRequestSvecObject other = (CompositeRequestSvecObject) obj;
+               if (this.excludeRoute == null) {
+                       if (other.excludeRoute != null)
+                               return false;
+               } else if (!this.excludeRoute.equals(other.excludeRoute))
+                       return false;
+               if (this.globalConstraints == null) {
+                       if (other.globalConstraints != null)
+                               return false;
+               } else if (!this.globalConstraints.equals(other.globalConstraints))
+                       return false;
+               if (this.metrics == null) {
+                       if (other.metrics != null)
+                               return false;
+               } else if (!this.metrics.equals(other.metrics))
+                       return false;
+               if (this.objectiveFunction == null) {
+                       if (other.objectiveFunction != null)
+                               return false;
+               } else if (!this.objectiveFunction.equals(other.objectiveFunction))
+                       return false;
+               if (this.svec == null) {
+                       if (other.svec != null)
+                               return false;
+               } else if (!this.svec.equals(other.svec))
+                       return false;
+               return true;
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeResponseObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeResponseObject.java
new file mode 100644 (file)
index 0000000..a725dcc
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.5">Path
+ *      Computation Reply (PCRep) Message</a> - &lt;response&gt;</br>
+ */
+public class CompositeResponseObject {
+
+       private final PCEPRequestParameterObject requestParameter;
+
+       private final PCEPNoPathObject noPath;
+
+       private final PCEPLspObject lsp;
+
+       private final PCEPLspaObject lspa;
+
+       private final PCEPRequestedPathBandwidthObject bandwidth;
+
+       private List<PCEPMetricObject> metrics;
+
+       private final PCEPIncludeRouteObject includeRoute;
+
+       private List<CompositePathObject> paths;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        *
+        * @param requestParameter
+        *            PCEPRequestParameterObject. Can't be null.
+        */
+       public CompositeResponseObject(PCEPRequestParameterObject requestParameter) {
+               this(requestParameter, null, null, null, null, null, null, null);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        *
+        * @param requestParameter
+        *            PCEPRequestParameterObject. Can't be null.
+        * @param noPath
+        *            PCEPNoPathObject
+        * @param lsp
+        *            PCEPLspObject
+        * @param lspa
+        *            PCEPLspaObject
+        * @param bandwidth
+        *            PCEPRequestedPathBandwidthObject
+        * @param metrics
+        *            List<PCEPMetricObject>
+        * @param includeRoute
+        *            PCEPIncludeRouteObject
+        * @param paths
+        *            List<CompositePathObject>
+        */
+       public CompositeResponseObject(PCEPRequestParameterObject requestParameter, PCEPNoPathObject noPath, PCEPLspObject lsp, PCEPLspaObject lspa,
+                       PCEPRequestedPathBandwidthObject bandwidth, List<PCEPMetricObject> metrics, PCEPIncludeRouteObject includeRoute, List<CompositePathObject> paths) {
+               if (requestParameter == null)
+                       throw new IllegalArgumentException("Request Parameter Object is mandatory.");
+               this.requestParameter = requestParameter;
+               this.noPath = noPath;
+               this.lsp = lsp;
+               this.lspa = lspa;
+               this.bandwidth = bandwidth;
+               if (metrics != null)
+                       this.metrics = metrics;
+               else
+                       this.metrics = Collections.emptyList();
+               this.includeRoute = includeRoute;
+               if (paths != null)
+                       this.paths = paths;
+               else
+                       this.paths = Collections.emptyList();
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        *
+        * @return List<PCEPObject>
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               list.add(this.requestParameter);
+               if (this.noPath != null)
+                       list.add(this.noPath);
+               if (this.lsp != null)
+                       list.add(this.lsp);
+               if (this.lspa != null)
+                       list.add(this.lspa);
+               if (this.bandwidth != null)
+                       list.add(this.bandwidth);
+               if (this.metrics != null && !this.metrics.isEmpty())
+                       list.addAll(this.metrics);
+               if (this.includeRoute != null)
+                       list.add(this.includeRoute);
+               if (this.paths != null && !this.paths.isEmpty())
+                       for (final CompositePathObject cpo : this.paths)
+                               list.addAll(cpo.getCompositeAsList());
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * @param objects List<PCEPObject> list of PCEPObjects from whose this
+        * object should be created.
+        * @return CompositeResponseObject
+        */
+       public static CompositeResponseObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+               }
+               PCEPRequestParameterObject requestParameter = null;
+               if (objects.get(0) instanceof PCEPRequestParameterObject) {
+                       requestParameter = (PCEPRequestParameterObject) objects.get(0);
+                       objects.remove(requestParameter);
+               } else
+                       return null;
+               PCEPNoPathObject noPath = null;
+               PCEPLspObject lsp = null;
+               PCEPLspaObject lspa = null;
+               PCEPRequestedPathBandwidthObject bandwidth = null;
+               final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+               PCEPIncludeRouteObject iro = null;
+               final List<CompositePathObject> paths = new ArrayList<CompositePathObject>();
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPNoPathObject) {
+                                               noPath = (PCEPNoPathObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPLspObject) {
+                                               lsp = (PCEPLspObject) obj;
+                                               break;
+                                       }
+                               case 3:
+                                       state = 4;
+                                       if (obj instanceof PCEPLspaObject) {
+                                               lspa = (PCEPLspaObject) obj;
+                                               break;
+                                       }
+                               case 4:
+                                       state = 5;
+                                       if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                                               bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+                                               break;
+                                       }
+                               case 5:
+                                       if (obj instanceof PCEPMetricObject) {
+                                               metrics.add((PCEPMetricObject) obj);
+                                               state = 5;
+                                               break;
+                                       } else
+                                               state = 6;
+                               case 6:
+                                       state = 8;
+                                       if (obj instanceof PCEPIncludeRouteObject) {
+                                               iro = (PCEPIncludeRouteObject) obj;
+                                               break;
+                                       }
+                                       state = 7;
+                       }
+
+                       if (state == 7) {
+                               break;
+                       }
+                       objects.remove(obj);
+                       if (state == 8) {
+                               break;
+                       }
+               }
+               if (!objects.isEmpty()) {
+                       CompositePathObject path = CompositePathObject.getCompositeFromList(objects);
+                       while (path != null) {
+                               paths.add(path);
+                               if (objects.isEmpty())
+                                       break;
+                               path = CompositePathObject.getCompositeFromList(objects);
+                       }
+               }
+               return new CompositeResponseObject(requestParameter, noPath, lsp, lspa, bandwidth, metrics, iro, paths);
+       }
+
+       /**
+        * Gets {@link PCEPRequestParameterObject}.
+        *
+        * @return PCEPRequestParameterObject. Can't be null.
+        */
+       public PCEPRequestParameterObject getRequestParameter() {
+               return this.requestParameter;
+       }
+
+       /**
+        * Gets {@link PCEPNoPathObject}.
+        *
+        * @return PCEPNoPathObject. May be null.
+        */
+       public PCEPNoPathObject getNoPath() {
+               return this.noPath;
+       }
+
+       /**
+        * Gets {@link PCEPLspObject}
+        *
+        * @return PCEPLspObject. May be null.
+        */
+       public PCEPLspObject getLsp() {
+               return this.lsp;
+       }
+
+       /**
+        * Gets {@link PCEPLspaObject}.
+        *
+        * @return PCEPLspaObject. May be null.
+        */
+       public PCEPLspaObject getLspa() {
+               return this.lspa;
+       }
+
+       /**
+        * Gets {@link PCEPBandwidthObject}.
+        *
+        * @return PCEPBandwidthObject. May be null.
+        */
+       public PCEPBandwidthObject getBandwidth() {
+               return this.bandwidth;
+       }
+
+       /**
+        * Gets list of {@link PCEPMetricObject}.
+        *
+        * @return List<PCEPMetricObject>. Can't be null, but may be empty.
+        */
+       public List<PCEPMetricObject> getMetrics() {
+               return this.metrics;
+       }
+
+       /**
+        * Gets list of {@link CompositePathObject}.
+        *
+        * @return PCEPIncludeRouteObject. Can't be null, but may be empty.
+        */
+       public PCEPIncludeRouteObject getIncludeRoute() {
+               return this.includeRoute;
+       }
+
+       /**
+        * Gets list of {@link CompositePathObject}.
+        *
+        * @return List<CompositePathObject>. Can't be null, but may be empty.
+        */
+       public List<CompositePathObject> getPaths() {
+               return this.paths;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+               result = prime * result + ((this.includeRoute == null) ? 0 : this.includeRoute.hashCode());
+               result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+               result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+               result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+               result = prime * result + ((this.noPath == null) ? 0 : this.noPath.hashCode());
+               result = prime * result + ((this.paths == null) ? 0 : this.paths.hashCode());
+               result = prime * result + ((this.requestParameter == null) ? 0 : this.requestParameter.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final CompositeResponseObject other = (CompositeResponseObject) obj;
+               if (this.bandwidth == null) {
+                       if (other.bandwidth != null)
+                               return false;
+               } else if (!this.bandwidth.equals(other.bandwidth))
+                       return false;
+               if (this.includeRoute == null) {
+                       if (other.includeRoute != null)
+                               return false;
+               } else if (!this.includeRoute.equals(other.includeRoute))
+                       return false;
+               if (this.lsp == null) {
+                       if (other.lsp != null)
+                               return false;
+               } else if (!this.lsp.equals(other.lsp))
+                       return false;
+               if (this.lspa == null) {
+                       if (other.lspa != null)
+                               return false;
+               } else if (!this.lspa.equals(other.lspa))
+                       return false;
+               if (this.metrics == null) {
+                       if (other.metrics != null)
+                               return false;
+               } else if (!this.metrics.equals(other.metrics))
+                       return false;
+               if (this.noPath == null) {
+                       if (other.noPath != null)
+                               return false;
+               } else if (!this.noPath.equals(other.noPath))
+                       return false;
+               if (this.paths == null) {
+                       if (other.paths != null)
+                               return false;
+               } else if (!this.paths.equals(other.paths))
+                       return false;
+               if (this.requestParameter == null) {
+                       if (other.requestParameter != null)
+                               return false;
+               } else if (!this.requestParameter.equals(other.requestParameter))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeResponseObject [requestParameter=");
+               builder.append(this.requestParameter);
+               builder.append(", noPath=");
+               builder.append(this.noPath);
+               builder.append(", lsp=");
+               builder.append(this.lsp);
+               builder.append(", lspa=");
+               builder.append(this.lspa);
+               builder.append(", bandwidth=");
+               builder.append(this.bandwidth);
+               builder.append(", metrics=");
+               builder.append(this.metrics);
+               builder.append(", includeRoute=");
+               builder.append(this.includeRoute);
+               builder.append(", paths=");
+               builder.append(this.paths);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeRptPathObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeRptPathObject.java
new file mode 100644 (file)
index 0000000..56ed287
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-6.1">PCRpt
+ *      Message</a>
+ */
+public class CompositeRptPathObject {
+       private final PCEPExplicitRouteObject explicitRoute;
+
+       private final PCEPLspaObject lspa;
+
+       private final PCEPExistingPathBandwidthObject bandwidth;
+
+       private final PCEPReportedRouteObject reportedRoute;
+
+       private List<PCEPMetricObject> metrics;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        *
+        * @param explicitRoute
+        *            PCEPExplicitRouteObject. Can't be null.
+        */
+       public CompositeRptPathObject(final PCEPExplicitRouteObject explicitRoute) {
+               this(explicitRoute, null, null, null, null);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        *
+        * @param explicitRoute
+        *            PCEPExplicitRouteObject. Can't be null.
+        * @param lspa
+        *            PCEPLspaObject
+        * @param bandwidth
+        *            PCEPRequestedPathBandwidthObject
+        * @param reportedRoute
+        *            PCEPReportedRouteObject
+        * @param metrics
+        *            List<PCEPMetricObject>
+        */
+       public CompositeRptPathObject(final PCEPExplicitRouteObject explicitRoute, final PCEPLspaObject lspa, final PCEPExistingPathBandwidthObject bandwidth,
+                       final PCEPReportedRouteObject reportedRoute, final List<PCEPMetricObject> metrics) {
+               if (explicitRoute == null)
+                       throw new IllegalArgumentException("Explicit Route Object is mandatory.");
+               this.explicitRoute = explicitRoute;
+               this.lspa = lspa;
+               this.bandwidth = bandwidth;
+               if (metrics != null)
+                       this.metrics = metrics;
+               else
+                       this.metrics = Collections.emptyList();
+               this.reportedRoute = reportedRoute;
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        *
+        * @return List<PCEPObject>. Can't be null or empty.
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               list.add(this.explicitRoute);
+               if (this.lspa != null)
+                       list.add(this.lspa);
+               if (this.bandwidth != null)
+                       list.add(this.bandwidth);
+               if (this.reportedRoute != null)
+                       list.add(this.reportedRoute);
+               if (this.metrics != null && !this.metrics.isEmpty())
+                       list.addAll(this.metrics);
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * @param objects List<PCEPObject> list of PCEPObjects from whose this
+        * object should be created.
+        * @return CompositeRptPathObject
+        */
+       public static CompositeRptPathObject getCompositeFromList(final List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+               }
+
+               PCEPExplicitRouteObject explicitRoute = null;
+               if (objects.get(0) instanceof PCEPExplicitRouteObject) {
+                       explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+                       objects.remove(explicitRoute);
+               } else
+                       return null;
+
+               PCEPLspaObject lspa = null;
+               PCEPExistingPathBandwidthObject bandwidth = null;
+               final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+               PCEPReportedRouteObject rro = null;
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPLspaObject) {
+                                               lspa = (PCEPLspaObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPExistingPathBandwidthObject) {
+                                               bandwidth = (PCEPExistingPathBandwidthObject) obj;
+                                               break;
+                                       }
+                               case 3:
+                                       state = 4;
+                                       if (obj instanceof PCEPReportedRouteObject) {
+                                               rro = (PCEPReportedRouteObject) obj;
+                                               break;
+                                       }
+                               case 4:
+                                       if (obj instanceof PCEPMetricObject) {
+                                               metrics.add((PCEPMetricObject) obj);
+                                               state = 4;
+                                               break;
+                                       } else
+                                               state = 5;
+                       }
+
+                       if (state == 5) {
+                               break;
+                       }
+
+                       objects.remove(obj);
+               }
+
+               return new CompositeRptPathObject(explicitRoute, lspa, bandwidth, rro, metrics);
+       }
+
+       /**
+        * Gets {@link PCEPExplicitRouteObject}.
+        *
+        * @return PCEPExplicitRouteObject. Can't be null.
+        */
+       public PCEPExplicitRouteObject getExcludedRoute() {
+               return this.explicitRoute;
+       }
+
+       /**
+        * Gets {@link PCEPLspaObject}.
+        *
+        * @return PCEPLspaObject. May be null.
+        */
+       public PCEPLspaObject getLspa() {
+               return this.lspa;
+       }
+
+       /**
+        * Gets {@link PCEPBandwidthObject}.
+        *
+        * @return PCEPBandwidthObject. May be null.
+        */
+       public PCEPBandwidthObject getBandwidth() {
+               return this.bandwidth;
+       }
+
+       /**
+        * Gets list of {@link PCEPMetricObject}.
+        *
+        * @return List<PCEPMetricObject>. Can't be null, but may be empty.
+        */
+       public List<PCEPMetricObject> getMetrics() {
+               return this.metrics;
+       }
+
+       /**
+        * Gets {@link PCEPReportedRouteObject}.
+        *
+        * @return PCEPReportedRouteObject. May be null.
+        */
+       public PCEPReportedRouteObject getReportedRoute() {
+               return this.reportedRoute;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+               result = prime * result + ((this.explicitRoute == null) ? 0 : this.explicitRoute.hashCode());
+               result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+               result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+               result = prime * result + ((this.reportedRoute == null) ? 0 : this.reportedRoute.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final CompositeRptPathObject other = (CompositeRptPathObject) obj;
+               if (this.bandwidth == null) {
+                       if (other.bandwidth != null)
+                               return false;
+               } else if (!this.bandwidth.equals(other.bandwidth))
+                       return false;
+               if (this.explicitRoute == null) {
+                       if (other.explicitRoute != null)
+                               return false;
+               } else if (!this.explicitRoute.equals(other.explicitRoute))
+                       return false;
+               if (this.lspa == null) {
+                       if (other.lspa != null)
+                               return false;
+               } else if (!this.lspa.equals(other.lspa))
+                       return false;
+               if (this.metrics == null) {
+                       if (other.metrics != null)
+                               return false;
+               } else if (!this.metrics.equals(other.metrics))
+                       return false;
+               if (this.reportedRoute == null) {
+                       if (other.reportedRoute != null)
+                               return false;
+               } else if (!this.reportedRoute.equals(other.reportedRoute))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeRptPathObject [explicitRoute=");
+               builder.append(this.explicitRoute);
+               builder.append(", lspa=");
+               builder.append(this.lspa);
+               builder.append(", bandwidth=");
+               builder.append(this.bandwidth);
+               builder.append(", reportedRoute=");
+               builder.append(this.reportedRoute);
+               builder.append(", metrics=");
+               builder.append(this.metrics);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeStateReportObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeStateReportObject.java
new file mode 100644 (file)
index 0000000..5146956
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-6.1">The
+ *      PCRpt Message</a> - &lt;state-report&gt;</br>
+ */
+public class CompositeStateReportObject {
+
+       private final PCEPLspObject lsp;
+
+       private List<CompositeRptPathObject> paths;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        *
+        * @param lsp
+        *            PCEPLspObject
+        */
+       public CompositeStateReportObject(PCEPLspObject lsp) {
+               this(lsp, null);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        *
+        * @param lsp
+        *            PCEPLspObject
+        * @param paths
+        *            List<CompositeRptPathObject> Can't be null.
+        */
+       public CompositeStateReportObject(PCEPLspObject lsp, List<CompositeRptPathObject> paths) {
+               if (lsp == null)
+                       throw new IllegalArgumentException("LSP Object is mandatory.");
+               this.lsp = lsp;
+               if (paths != null)
+                       this.paths = paths;
+               else
+                       this.paths = Collections.emptyList();
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * @param objects List<PCEPObject> list of PCEPObjects from whose this
+        * object should be created.
+        * @return CompositeStateReportObject
+        */
+       public static CompositeStateReportObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List can not be null or empty.");
+               }
+
+               PCEPLspObject lsp = null;
+               if (objects.get(0) instanceof PCEPLspObject) {
+                       lsp = (PCEPLspObject) objects.get(0);
+                       objects.remove(lsp);
+               } else
+                       return null;
+
+               final List<CompositeRptPathObject> paths = new ArrayList<CompositeRptPathObject>();
+
+               if (!objects.isEmpty()) {
+                       CompositeRptPathObject path = CompositeRptPathObject.getCompositeFromList(objects);
+                       while (path != null) {
+                               paths.add(path);
+                               if (objects.isEmpty())
+                                       break;
+                               path = CompositeRptPathObject.getCompositeFromList(objects);
+                       }
+               }
+
+               return new CompositeStateReportObject(lsp, paths);
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        *
+        * @return List<PCEPObject>
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               list.add(this.lsp);
+               if (this.paths != null && !this.paths.isEmpty())
+                       for (final CompositeRptPathObject cpo : this.paths)
+                               list.addAll(cpo.getCompositeAsList());
+               return list;
+       }
+
+       /**
+        * Gets {@link PCEPLspObject}.
+        *
+        * @return PCEPLspObject. Can't be null.
+        */
+       public PCEPLspObject getLsp() {
+               return this.lsp;
+       }
+
+       /**
+        * Gets list of {@link CompositeRptPathObject}.
+        *
+        * @return List<CompositeRptPathObject>. May be null.
+        */
+       public List<CompositeRptPathObject> getPaths() {
+               return this.paths;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+               result = prime * result + ((this.paths == null) ? 0 : this.paths.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final CompositeStateReportObject other = (CompositeStateReportObject) obj;
+               if (this.lsp == null) {
+                       if (other.lsp != null)
+                               return false;
+               } else if (!this.lsp.equals(other.lsp))
+                       return false;
+               if (this.paths == null) {
+                       if (other.paths != null)
+                               return false;
+               } else if (!this.paths.equals(other.paths))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeStateReportObject [lsp=");
+               builder.append(this.lsp);
+               builder.append(", paths=");
+               builder.append(this.paths);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeUpdPathObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeUpdPathObject.java
new file mode 100644 (file)
index 0000000..a6d845a
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see draft-ietf-pce-stateful-pce-01 (sec. 6.2) - The PCUpd Message -
+ *      &lt;path&gt;</br>
+ */
+public class CompositeUpdPathObject {
+
+       private final PCEPExplicitRouteObject explicitRoute;
+
+       private final PCEPLspaObject lspa;
+
+       private final PCEPRequestedPathBandwidthObject bandwidth;
+
+       private List<PCEPMetricObject> metrics;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        * @param explicitRoute PCEPExplicitRouteObject
+        */
+       public CompositeUpdPathObject(PCEPExplicitRouteObject explicitRoute) {
+               this(explicitRoute, null, null, null);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        * @param explicitRoute PCEPExplicitRouteObject
+        * @param lspa PCEPLspaObject
+        * @param bandwidth PCEPRequestedPathBandwidthObject
+        * @param metrics List<PCEPMetricObject>
+        */
+       public CompositeUpdPathObject(PCEPExplicitRouteObject explicitRoute, PCEPLspaObject lspa, PCEPRequestedPathBandwidthObject bandwidth,
+                       List<PCEPMetricObject> metrics) {
+               if (explicitRoute == null)
+                       throw new IllegalArgumentException("Explicit Route Object is mandatory.");
+               this.explicitRoute = explicitRoute;
+               this.lspa = lspa;
+               this.bandwidth = bandwidth;
+               if (metrics != null)
+                       this.metrics = metrics;
+               else
+                       this.metrics = Collections.emptyList();
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        * @return List<PCEPObject>
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               list.add(this.explicitRoute);
+               if (this.lspa != null)
+                       list.add(this.lspa);
+               if (this.bandwidth != null)
+                       list.add(this.bandwidth);
+               if (this.metrics != null && !this.metrics.isEmpty())
+                       list.addAll(this.metrics);
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * @param objects List<PCEPObject> list of PCEPObjects from whose this
+        * object should be created.
+        * @return CompositeUpdPathObject constructed from objects
+        */
+       public static CompositeUpdPathObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+               }
+
+               PCEPExplicitRouteObject explicitRoute = null;
+               if (objects.get(0) instanceof PCEPExplicitRouteObject) {
+                       explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+                       objects.remove(explicitRoute);
+               } else
+                       return null;
+
+               PCEPLspaObject lspa = null;
+               PCEPRequestedPathBandwidthObject bandwidth = null;
+               final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPLspaObject) {
+                                               lspa = (PCEPLspaObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                                               bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+                                               break;
+                                       }
+                               case 3:
+                                       if (obj instanceof PCEPMetricObject) {
+                                               metrics.add((PCEPMetricObject) obj);
+                                               state = 3;
+                                               break;
+                                       } else
+                                               state = 4;
+                       }
+
+                       if (state == 4) {
+                               break;
+                       }
+
+                       objects.remove(obj);
+               }
+
+               return new CompositeUpdPathObject(explicitRoute, lspa, bandwidth, metrics);
+       }
+
+       /**
+        * Gets {@link PCEPExplicitRouteObject}
+        *
+        * @return PCEPExplicitRouteObject
+        */
+       public PCEPExplicitRouteObject getExcludedRoute() {
+               return this.explicitRoute;
+       }
+
+       /**
+        * Gets {@link PCEPLspaObject}
+        *
+        * @return PCEPLspaObject
+        */
+       public PCEPLspaObject getLspa() {
+               return this.lspa;
+       }
+
+       /**
+        * Gets bandwidth.
+        *
+        * @return PCEPBandwidthObject
+        */
+       public PCEPBandwidthObject getBandwidth() {
+               return this.bandwidth;
+       }
+
+       /**
+        * Gets list of {@link PCEPMetricObject}.
+        *
+        * @return List<PCEPMetricObject>
+        */
+       public List<PCEPMetricObject> getMetrics() {
+               return this.metrics;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+               result = prime * result + ((this.explicitRoute == null) ? 0 : this.explicitRoute.hashCode());
+               result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+               result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final CompositeUpdPathObject other = (CompositeUpdPathObject) obj;
+               if (this.bandwidth == null) {
+                       if (other.bandwidth != null)
+                               return false;
+               } else if (!this.bandwidth.equals(other.bandwidth))
+                       return false;
+               if (this.explicitRoute == null) {
+                       if (other.explicitRoute != null)
+                               return false;
+               } else if (!this.explicitRoute.equals(other.explicitRoute))
+                       return false;
+               if (this.lspa == null) {
+                       if (other.lspa != null)
+                               return false;
+               } else if (!this.lspa.equals(other.lspa))
+                       return false;
+               if (this.metrics == null) {
+                       if (other.metrics != null)
+                               return false;
+               } else if (!this.metrics.equals(other.metrics))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeUpdPathObject [explicitRoute=");
+               builder.append(this.explicitRoute);
+               builder.append(", lspa=");
+               builder.append(this.lspa);
+               builder.append(", bandwidth=");
+               builder.append(this.bandwidth);
+               builder.append(", metrics=");
+               builder.append(this.metrics);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeUpdateRequestObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/CompositeUpdateRequestObject.java
new file mode 100644 (file)
index 0000000..7f05f1d
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-6.2">The
+ *      PCRpt Message</a> - &lt;update-request&gt;</br>
+ */
+public class CompositeUpdateRequestObject {
+
+       private final PCEPLspObject lsp;
+
+       private List<CompositeUpdPathObject> paths;
+
+       /**
+        * Constructs basic composite object only with mandatory objects.
+        *
+        * @param lsp
+        *            PCEPLspObject. Can't be null.
+        */
+       public CompositeUpdateRequestObject(PCEPLspObject lsp) {
+               this(lsp, null);
+       }
+
+       /**
+        * Constructs composite object with optional objects.
+        *
+        * @param lsp
+        *            PCEPLspObject. Can't be null.
+        * @param paths
+        *            List<CompositeUpdPathObject>
+        */
+       public CompositeUpdateRequestObject(PCEPLspObject lsp, List<CompositeUpdPathObject> paths) {
+               if (lsp == null)
+                       throw new IllegalArgumentException("LSP Object is mandatory.");
+               this.lsp = lsp;
+               if (paths != null)
+                       this.paths = paths;
+               else
+                       this.paths = Collections.emptyList();
+       }
+
+       /**
+        * Gets list of all objects, which are in appropriate order.
+        *
+        * @return List<PCEPObject>. Can't be null.
+        */
+       public List<PCEPObject> getCompositeAsList() {
+               final List<PCEPObject> list = new ArrayList<PCEPObject>();
+               list.add(this.lsp);
+               if (this.paths != null && !this.paths.isEmpty())
+                       for (final CompositeUpdPathObject cpo : this.paths)
+                               list.addAll(cpo.getCompositeAsList());
+               return list;
+       }
+
+       /**
+        * Creates this object from a list of PCEPObjects.
+        * @param objects List<PCEPObject> list of PCEPObjects from whose this
+        * object should be created.
+        * @return CompositeUpdateRequestObject
+        */
+       public static CompositeUpdateRequestObject getCompositeFromList(List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+               }
+
+               PCEPLspObject lsp = null;
+               if (objects.get(0) instanceof PCEPLspObject) {
+                       lsp = (PCEPLspObject) objects.get(0);
+                       objects.remove(lsp);
+               } else
+                       return null;
+
+               final List<CompositeUpdPathObject> paths = new ArrayList<CompositeUpdPathObject>();
+
+               if (!objects.isEmpty()) {
+                       CompositeUpdPathObject path = CompositeUpdPathObject.getCompositeFromList(objects);
+                       while (path != null) {
+                               paths.add(path);
+                               if (objects.isEmpty())
+                                       break;
+                               path = CompositeUpdPathObject.getCompositeFromList(objects);
+                       }
+               }
+
+               return new CompositeUpdateRequestObject(lsp, paths);
+       }
+
+       /**
+        * Gets {@link PCEPLspObject}.
+        *
+        * @return PCEPLspObject. Can't be null.
+        */
+       public PCEPLspObject getLsp() {
+               return this.lsp;
+       }
+
+       /**
+        * Gets list of {@link CompositeUpdPathObject}.
+        *
+        * @return List<CompositeUpdPathObject>. Can't be null, but may be empty.
+        */
+       public List<CompositeUpdPathObject> getPaths() {
+               return this.paths;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+               result = prime * result + ((this.paths == null) ? 0 : this.paths.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final CompositeUpdateRequestObject other = (CompositeUpdateRequestObject) obj;
+               if (this.lsp == null) {
+                       if (other.lsp != null)
+                               return false;
+               } else if (!this.lsp.equals(other.lsp))
+                       return false;
+               if (this.paths == null) {
+                       if (other.paths != null)
+                               return false;
+               } else if (!this.paths.equals(other.paths))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("CompositeUpdateRequestObject [lsp=");
+               builder.append(this.lsp);
+               builder.append(", paths=");
+               builder.append(this.paths);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPBandwidthObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPBandwidthObject.java
new file mode 100644 (file)
index 0000000..11d46c8
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Basic structure of Bandwidth Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.7">PCEP Bandwidth
+ *      Object</a>
+ */
+public abstract class PCEPBandwidthObject extends PCEPObject {
+
+    private final Bandwidth bandwidth;
+
+    /**
+     * Constructs basic Bandwidth Object.
+     *
+     * @param bandwidth
+     *            Bandwidth
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPBandwidthObject(Bandwidth bandwidth, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       if (bandwidth == null)
+           this.bandwidth = new Bandwidth(0f);
+       else
+           this.bandwidth = bandwidth;
+    }
+
+    /**
+     * Gets {@link PCEPBandwidthObject}.
+     *
+     * @return Bandwidth. Can't be null.
+     */
+    public Bandwidth getBandwidth() {
+       return this.bandwidth;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPBandwidthObject other = (PCEPBandwidthObject) obj;
+       if (this.bandwidth == null) {
+           if (other.bandwidth != null)
+               return false;
+       } else if (!this.bandwidth.equals(other.bandwidth))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("bandwidth", this.bandwidth);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPBranchNodeListObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPBranchNodeListObject.java
new file mode 100644 (file)
index 0000000..27b5251
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Structure of Branch Node list object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc6006#section-3.11.1">Branch Node
+ *      Object [RFC6006]</a>
+ */
+public class PCEPBranchNodeListObject extends PCEPBranchNodeObject {
+
+    /**
+     * Constructs Branch Node list object.
+     *
+     * @param subobjects
+     *            List<ExplicitRouteSubobject>
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPBranchNodeListObject(List<ExplicitRouteSubobject> subobjects, boolean processed, boolean ignored) {
+       super(subobjects, processed, ignored);
+    }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPBranchNodeObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPBranchNodeObject.java
new file mode 100644 (file)
index 0000000..3c2cd97
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ *
+ */
+public abstract class PCEPBranchNodeObject extends PCEPObject {
+
+    protected final List<ExplicitRouteSubobject> subobjects;
+
+    /**
+     * Constructs Branch Node list object.
+     *
+     * @param subobjects
+     *            List<PCEPSubobject>
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPBranchNodeObject(List<ExplicitRouteSubobject> subobjects, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       if (subobjects == null || subobjects.isEmpty())
+           throw new IllegalArgumentException("Subobjects can't be null or empty.");
+       this.subobjects = subobjects;
+    }
+
+    /**
+     * Gets list of {@link ExplicitRouteSubobject}
+     *
+     * @return List<ExplicitRouteSubobject>. Can't be null or empty.
+     */
+    public List<ExplicitRouteSubobject> getSubobjects() {
+       return this.subobjects;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPBranchNodeObject other = (PCEPBranchNodeObject) obj;
+       if (this.subobjects == null) {
+           if (other.subobjects != null)
+               return false;
+       } else if (!this.subobjects.equals(other.subobjects))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("subobjects", this.subobjects);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPClassTypeObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPClassTypeObject.java
new file mode 100644 (file)
index 0000000..70648c6
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of ClassType Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5455#section-5"> Object
+ *      Definition</a>
+ */
+public class PCEPClassTypeObject extends PCEPObject {
+
+    private final short classType;
+
+    /**
+     * Constructs ClassType Object with given class type.
+     *
+     * @param classType
+     *            short, must be positive and less than 8.
+     */
+    public PCEPClassTypeObject(short classType) {
+       super(true, false);
+       if (classType < 0 || classType > 7) {
+           throw new IllegalArgumentException("ClassType range overstepped.");
+       }
+       this.classType = classType;
+    }
+
+    /**
+     * Gets class type.
+     *
+     * @return class type
+     */
+    public short getClassType() {
+       return this.classType;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + this.classType;
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (!(obj instanceof PCEPClassTypeObject))
+           return false;
+       final PCEPClassTypeObject other = (PCEPClassTypeObject) obj;
+       if (this.classType != other.classType)
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("classType", this.classType);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPCloseObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPCloseObject.java
new file mode 100644 (file)
index 0000000..bf4217a
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Close Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.17">PCEP Close
+ *      Object</a>
+ */
+public class PCEPCloseObject extends PCEPObject {
+
+       /**
+        * Constants for reasons of closing session.
+        */
+       public enum Reason {
+               UNKNOWN, EXP_DEADTIMER, MALFORMED_MSG, TOO_MANY_UNKNOWN_REQ_REP, TOO_MANY_UNKNOWN_MSG
+       }
+
+       private final Reason reason;
+
+       private List<PCEPTlv> tlvs;
+
+       /**
+        * Constructs Close Object only with mandatory object.
+        *
+        * @param reason
+        *            Reason. Can't be null.
+        */
+       public PCEPCloseObject(Reason reason) {
+               this(reason, null);
+       }
+
+       /**
+        * Constructs Close Object also with optional objects.
+        *
+        * @param reason
+        *            Reason. Can't be null.
+        * @param tlvs
+        *            List<PCEPTlv>
+        */
+       public PCEPCloseObject(Reason reason, List<PCEPTlv> tlvs) {
+               super(false, false);
+               if (reason == null)
+                       throw new IllegalArgumentException("Reason is mandatory.");
+               this.reason = reason;
+
+               if (tlvs != null)
+                       this.tlvs = tlvs;
+               else
+                       this.tlvs = Collections.emptyList();
+       }
+
+       /**
+        * Gets {@link Reason}
+        *
+        * @return Reason. Can't be null.
+        */
+       public Reason getReason() {
+               return this.reason;
+       }
+
+       /**
+        * Gets list of {@link PCEPTlv}
+        *
+        * @return List<PCEPTlv>. Can't be null, but may be empty.
+        */
+       public List<PCEPTlv> getTlvs() {
+               return this.tlvs;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.reason == null) ? 0 : this.reason.hashCode());
+               result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPCloseObject other = (PCEPCloseObject) obj;
+               if (this.reason != other.reason)
+                       return false;
+               if (this.tlvs == null) {
+                       if (other.tlvs != null)
+                               return false;
+               } else if (!this.tlvs.equals(other.tlvs))
+                       return false;
+               return true;
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("reason", this.reason);
+               toStringHelper.add("tlvs", this.tlvs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPEndPoints.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPEndPoints.java
new file mode 100644 (file)
index 0000000..c475fc5
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+public abstract class PCEPEndPoints extends PCEPObject {
+
+    protected PCEPEndPoints(boolean processed, boolean ignored) {
+       super(processed, ignored);
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPEndPointsObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPEndPointsObject.java
new file mode 100644 (file)
index 0000000..987d969
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Parameterized structure of PCEP End Points Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.6">PCEP
+ *      EndPointsObject</a>
+ * @param <T>
+ *            subtype of NetworkAddress
+ */
+public class PCEPEndPointsObject<T extends NetworkAddress<T>> extends PCEPEndPoints {
+
+    private final T sourceAddress;
+
+    private final T destinationAddress;
+
+    /**
+     * Constructs Close Object with mandatory object.
+     *
+     * @param sourceAddress
+     *            T. Cant't be null.
+     * @param destinationAddress
+     *            T. Cant't be null.
+     */
+    public PCEPEndPointsObject(T sourceAddress, T destinationAddress) {
+       super(true, false);
+       if (sourceAddress == null)
+           throw new IllegalArgumentException("Source address is mantadory.");
+       this.sourceAddress = sourceAddress;
+       if (destinationAddress == null)
+           throw new IllegalArgumentException("Destination address is mantadory.");
+       this.destinationAddress = destinationAddress;
+    }
+
+    /**
+     * Gets source address of type T.
+     *
+     * @return T. Can't be null.
+     */
+    public T getSourceAddress() {
+       return this.sourceAddress;
+    }
+
+    /**
+     * Gets destination address of type T.
+     *
+     * @return T. Can't be null.
+     */
+    public T getDestinationAddress() {
+       return this.destinationAddress;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("sourceAddress", this.sourceAddress);
+               toStringHelper.add("destinationAddress", this.destinationAddress);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.destinationAddress == null) ? 0 : this.destinationAddress.hashCode());
+       result = prime * result + ((this.sourceAddress == null) ? 0 : this.sourceAddress.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (!(obj instanceof PCEPEndPointsObject))
+           return false;
+       final PCEPEndPointsObject<?> other = (PCEPEndPointsObject<?>) obj;
+       if (this.destinationAddress == null) {
+           if (other.destinationAddress != null)
+               return false;
+       } else if (!this.destinationAddress.equals(other.destinationAddress))
+           return false;
+       if (this.sourceAddress == null) {
+           if (other.sourceAddress != null)
+               return false;
+       } else if (!this.sourceAddress.equals(other.sourceAddress))
+           return false;
+       return true;
+    }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPErrorObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPErrorObject.java
new file mode 100644 (file)
index 0000000..3f1ab22
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Error Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.15">PCEP Error
+ *      Object</a>
+ */
+public class PCEPErrorObject extends PCEPObject {
+
+    private final PCEPErrors error;
+
+    private final List<PCEPTlv> tlvs;
+
+    /**
+     * Constructs Error Object only with mandatory object.
+     *
+     * @param type
+     *            PCEPErrors. Can't be null.
+     */
+    public PCEPErrorObject(PCEPErrors type) {
+       this(type, null);
+    }
+
+    /**
+     * Constructs Error Object also with optional objects.
+     *
+     * @param type
+     *            PCEPErrors. Can't be null
+     * @param tlvs
+     *            List<PCEPTlv>
+     */
+    public PCEPErrorObject(PCEPErrors type, List<PCEPTlv> tlvs) {
+       super(false, false);
+       this.error = type;
+       if (tlvs != null)
+           this.tlvs = tlvs;
+       else
+           this.tlvs = Collections.emptyList();
+    }
+
+    /**
+     * Gets {@link PCEPErrors}
+     *
+     * @return PCEPErrors. Can't be null.
+     */
+    public PCEPErrors getError() {
+       return this.error;
+    }
+
+    /**
+     * Gets list of {@link PCEPTlv}
+     *
+     * @return List<PCEPTlv>. Can't be null, but may be empty.
+     */
+    public List<PCEPTlv> getTlvs() {
+       return this.tlvs;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.error == null) ? 0 : this.error.hashCode());
+       result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPErrorObject other = (PCEPErrorObject) obj;
+       if (this.error != other.error)
+           return false;
+       if (this.tlvs == null) {
+           if (other.tlvs != null)
+               return false;
+       } else if (!this.tlvs.equals(other.tlvs))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("error", this.error);
+               toStringHelper.add("tlvs", this.tlvs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPExcludeRouteObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPExcludeRouteObject.java
new file mode 100644 (file)
index 0000000..a2fe0a8
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Provides a list of network resources that the PCE is requested to exclude
+ * from the path that it computes. Flags associated with each list member
+ * instruct the PCE as to whether the network resources must be excluded from
+ * the computed path, or whether the PCE should make best efforts to exclude the
+ * resources from the computed path.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1"> Exclude
+ *      Route Object definition</a>
+ */
+public class PCEPExcludeRouteObject extends PCEPObject {
+
+    private final boolean fail;
+
+    private final List<ExcludeRouteSubobject> subobjects;
+
+    /**
+     * Constructs Exclude Route Object.
+     *
+     * @param subobjects
+     *            List<PCEPXROSubobject>. Can't be null or empty.
+     * @param fail
+     *            boolean
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPExcludeRouteObject(List<ExcludeRouteSubobject> subobjects, boolean fail, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       if (subobjects == null || subobjects.isEmpty())
+           throw new IllegalArgumentException("Subobjects can't be null or empty.");
+
+       this.fail = fail;
+       this.subobjects = subobjects;
+    }
+
+    /**
+     * Gets list of sub-objects
+     *
+     * @return List<PCEPXROSubobject>. Can't be null or empty.
+     */
+    public List<ExcludeRouteSubobject> getSubobjects() {
+       return this.subobjects;
+    }
+
+    /**
+     * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1"> Exclude
+     *      Route Object definition</a>
+     *
+     * @return if returns true, the requesting PCC requires the computation of a
+     *         new path for an existing TE LSP that has failed
+     */
+    public boolean isFail() {
+       return this.fail;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("fail", this.fail);
+               toStringHelper.add("subobjects", this.subobjects);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPExcludeRouteObject other = (PCEPExcludeRouteObject) obj;
+       if (this.subobjects == null) {
+           if (other.subobjects != null)
+               return false;
+       } else if (!this.subobjects.equals(other.subobjects))
+           return false;
+       return true;
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPExistingPathBandwidthObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPExistingPathBandwidthObject.java
new file mode 100644 (file)
index 0000000..8b6ccab
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+
+/**
+ * Structure of specific Bandwidth. Used in Composite Requested Object to refer
+ * to bandwidth of existing path.
+ */
+public class PCEPExistingPathBandwidthObject extends PCEPBandwidthObject {
+
+    /**
+     * Constructs Existing Path Bandwidth.
+     *
+     * @param bandwidth
+     *            Bandwidth. Can't be null.
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPExistingPathBandwidthObject(Bandwidth bandwidth, boolean processed, boolean ignored) {
+       super(bandwidth, processed, ignored);
+    }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPExplicitRouteObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPExplicitRouteObject.java
new file mode 100644 (file)
index 0000000..2e571c2
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Explicit Route Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.9">PCEP Explicit
+ *      Route Object</a>
+ */
+public class PCEPExplicitRouteObject extends PCEPObject {
+
+    private final List<ExplicitRouteSubobject> subobjects;
+
+    /**
+     * Constructs Explicit Route Object.
+     *
+     * @param subobjects
+     *            List<ExplicitRouteSubobject>. Can't be null or empty.
+     * @param ignored
+     *            boolean
+     */
+    public PCEPExplicitRouteObject(List<ExplicitRouteSubobject> subobjects, boolean ignored) {
+       super(false, ignored);
+       if (subobjects == null || subobjects.isEmpty())
+           throw new IllegalArgumentException("Subobjects can't be null or empty.");
+       this.subobjects = subobjects;
+    }
+
+    /**
+     * Gets list of {@link ExplicitRouteSubobject}
+     *
+     * @return List<ExplicitRouteSubobject>. Can't be null or empty.
+     */
+    public List<ExplicitRouteSubobject> getSubobjects() {
+       return this.subobjects;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("subobjects", this.subobjects);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPExplicitRouteObject other = (PCEPExplicitRouteObject) obj;
+       if (this.subobjects == null) {
+           if (other.subobjects != null)
+               return false;
+       } else if (!this.subobjects.equals(other.subobjects))
+           return false;
+       return true;
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPGlobalConstraintsObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPGlobalConstraintsObject.java
new file mode 100644 (file)
index 0000000..19fe36d
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * The GLOBAL CONSTRAINTS Object is used in a PCReq message to specify the
+ * necessary global constraints that should be applied to all individual path
+ * computations for a global concurrent path optimization request.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5557#section-5.5">GLOBAL
+ *      CONSTRAINTS (GC) Object</a>
+ */
+public class PCEPGlobalConstraintsObject extends PCEPObject {
+
+    private final short maxHop;
+    private final short maxUtilization;
+    private final short minUtilization;
+    private final short overBookingFactor;
+
+    private List<PCEPTlv> tlvs;
+
+    /**
+     * Constructs Global Constraints Object with all mandatory fields.
+     *
+     * @param maxhop
+     *            8-bit integer
+     * @param maxUtilization
+     *            8-bit integer between 0 and 100
+     * @param minUtilization
+     *            8-bit integer between 0 and 100
+     * @param overBookingFactor
+     *            8-bit integer
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPGlobalConstraintsObject(short maxhop, short maxUtilization, short minUtilization, short overBookingFactor, boolean processed, boolean ignored) {
+       this(maxhop, maxUtilization, minUtilization, overBookingFactor, null, processed, ignored);
+    }
+
+    /**
+     * Constructs Global Constraints Object with all mandatory fields and
+     * optional list of tlvs.
+     *
+     * @param maxhop
+     *            8-bit integer
+     * @param maxUtilization
+     *            8-bit integer between 0 and 100
+     * @param minUtilization
+     *            8-bit integer between 0 and 100
+     * @param overBookingFactor
+     *            8-bit integer
+     * @param tlvs
+     *            list of tlvs
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPGlobalConstraintsObject(short maxhop, short maxUtilization, short minUtilization, short overBookingFactor, List<PCEPTlv> tlvs,
+           boolean processed, boolean ignored) {
+       super(processed, ignored);
+       this.maxHop = maxhop;
+
+       if (maxUtilization < 0 || maxUtilization > 100)
+           throw new IllegalArgumentException("Maximu utilization can be only between 0 and 100. Passed: " + maxUtilization);
+       this.maxUtilization = maxUtilization;
+
+       if (minUtilization < 0 || minUtilization > 100)
+           throw new IllegalArgumentException("Minimum utilization can be only between 0 and 100. Passed: " + minUtilization);
+       this.minUtilization = minUtilization;
+
+       this.overBookingFactor = overBookingFactor;
+
+       if (tlvs == null)
+           this.tlvs = Collections.emptyList();
+       else
+           this.tlvs = tlvs;
+    }
+
+    /**
+     * Gets the maximum hop count for all the TE LSPs
+     *
+     * @return the maximum hop count
+     */
+    public short getMaxHop() {
+       return this.maxHop;
+    }
+
+    /**
+     * Gets the maximum utilization percentage by which all links should be
+     * bound
+     *
+     * @return the maximum utilization percentage
+     */
+    public short getMaxUtilization() {
+       return this.maxUtilization;
+    }
+
+    /**
+     * Gets the minimum utilization percentage by which all links should be
+     * bound
+     *
+     * @return the maximum utilization percentage
+     */
+    public short getMinUtilization() {
+       return this.minUtilization;
+    }
+
+    /**
+     * Gets the over booking factor percentage that allows the reserved
+     * bandwidth to be overbooked on each link beyond its physical capacity
+     * limit
+     *
+     * @return the over booking factor percentage
+     */
+    public short getOverBookingFactor() {
+       return this.overBookingFactor;
+    }
+
+    /**
+     * Gets the list of optional tlvs
+     *
+     * @return List<PCEPTlv>. Can be empty but not null.
+     */
+    public List<PCEPTlv> getTlvs() {
+       return this.tlvs;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("maxHop", this.maxHop);
+               toStringHelper.add("maxUtilization", this.maxUtilization);
+               toStringHelper.add("minUtilization", this.minUtilization);
+               toStringHelper.add("overBookingFactor", this.overBookingFactor);
+               toStringHelper.add("tlvs", this.tlvs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + this.maxHop;
+       result = prime * result + this.maxUtilization;
+       result = prime * result + this.minUtilization;
+       result = prime * result + this.overBookingFactor;
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPGlobalConstraintsObject other = (PCEPGlobalConstraintsObject) obj;
+       if (this.maxHop != other.maxHop)
+           return false;
+       if (this.maxUtilization != other.maxUtilization)
+           return false;
+       if (this.minUtilization != other.minUtilization)
+           return false;
+       if (this.overBookingFactor != other.overBookingFactor)
+           return false;
+       return true;
+    }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPIncludeRouteObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPIncludeRouteObject.java
new file mode 100644 (file)
index 0000000..783eafe
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Explicit Route Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.12">PCEP Include
+ *      Route Object</a>
+ */
+public class PCEPIncludeRouteObject extends PCEPObject {
+
+    private final List<ExplicitRouteSubobject> subobjects;
+
+    /**
+     * Constructs Include Route Object.
+     *
+     * @param subobjects
+     *            List<ExplicitRouteSubobject>
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPIncludeRouteObject(List<ExplicitRouteSubobject> subobjects, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       if (subobjects == null || subobjects.isEmpty())
+           throw new IllegalArgumentException("Subobjects can't be null or empty.");
+       this.subobjects = subobjects;
+    }
+
+    /**
+     * Gets list of {@link ExplicitRouteSubobject}
+     *
+     * @return List<ExplicitRouteSubobject>. Can't be null or empty.
+     */
+    public List<ExplicitRouteSubobject> getSubobjects() {
+       return this.subobjects;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPIncludeRouteObject other = (PCEPIncludeRouteObject) obj;
+       if (this.subobjects == null) {
+           if (other.subobjects != null)
+               return false;
+       } else if (!this.subobjects.equals(other.subobjects))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("subobjects", this.subobjects);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPLoadBalancingObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPLoadBalancingObject.java
new file mode 100644 (file)
index 0000000..f545296
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure for PCEP Load Balancing Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.16">PCEP Load
+ *      Balancing Object</a>
+ */
+public class PCEPLoadBalancingObject extends PCEPObject {
+
+    private final int maxLSP;
+
+    private final Bandwidth minBandwidth;
+
+    /**
+     * Constructs Load Balancing Object.
+     *
+     * @param maxLSP
+     *            int
+     * @param minBandwidth
+     *            Bandwidth
+     * @param processed
+     *            boolean
+     */
+    public PCEPLoadBalancingObject(int maxLSP, Bandwidth minBandwidth, boolean processed) {
+       super(processed, false);
+       this.maxLSP = maxLSP;
+       this.minBandwidth = minBandwidth;
+    }
+
+    /**
+     * Gets Maximum LSP.
+     *
+     * @return int
+     */
+    public int getMaxLSP() {
+       return this.maxLSP;
+    }
+
+    /**
+     * Gets Minimal bandwidth.
+     *
+     * @return Bandwidth
+     */
+    public Bandwidth getMinBandwidth() {
+       return this.minBandwidth;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + this.maxLSP;
+       result = prime * result + ((this.minBandwidth == null) ? 0 : this.minBandwidth.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPLoadBalancingObject other = (PCEPLoadBalancingObject) obj;
+       if (this.maxLSP != other.maxLSP)
+           return false;
+       if (this.minBandwidth == null) {
+           if (other.minBandwidth != null)
+               return false;
+       } else if (!this.minBandwidth.equals(other.minBandwidth))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("maxLSP", this.maxLSP);
+               toStringHelper.add("minBandwidth", this.minBandwidth);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPLspObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPLspObject.java
new file mode 100644 (file)
index 0000000..e9d26f9
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP LSP Object.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-8.3">PCEP
+ *      LSP Object</a>
+ */
+public class PCEPLspObject extends PCEPObject {
+
+    private final int lspID;
+
+    private final boolean delegate;
+
+    private final boolean sync;
+
+    private final boolean operational;
+
+    private final boolean remove;
+
+    private final List<PCEPTlv> tlvs;
+
+    /**
+     * Constructs PCEP LSP Object only with mandatory values.
+     *
+     * @param lspID
+     *            int
+     * @param delegate
+     *            boolean
+     * @param sync
+     *            boolean
+     * @param operational
+     *            boolean
+     * @param remove
+     *            boolean
+     */
+    public PCEPLspObject(int lspID, boolean delegate, boolean sync, boolean operational, boolean remove) {
+       this(lspID, delegate, sync, operational, remove, null);
+    }
+
+    /**
+     * Constructs PCEP LSP Object also with optional Objects.
+     *
+     * @param lspID
+     *            int
+     * @param delegate
+     *            boolean
+     * @param sync
+     *            boolean
+     * @param operational
+     *            boolean
+     * @param remove
+     *            boolean
+     * @param tlvs
+     *            List<PCEPTlv>
+     */
+    public PCEPLspObject(int lspID, boolean delegate, boolean sync, boolean operational, boolean remove, List<PCEPTlv> tlvs) {
+       super(false, false);
+       this.lspID = lspID;
+       this.delegate = delegate;
+       this.sync = sync;
+       this.operational = operational;
+       this.remove = remove;
+       if (tlvs != null)
+           this.tlvs = tlvs;
+       else
+           this.tlvs = Collections.emptyList();
+    }
+
+    /**
+     * Gets integer representation of LSP ID.
+     *
+     * @return int
+     */
+    public int getLspID() {
+       return this.lspID;
+    }
+
+    /**
+     * Gets Delegate flag.
+     *
+     * @return boolean
+     */
+    public boolean isDelegate() {
+       return this.delegate;
+    }
+
+    /**
+     * Gets Sync flag.
+     *
+     * @return boolean
+     */
+    public boolean isSync() {
+       return this.sync;
+    }
+
+    /**
+     * Gets Operational flag.
+     *
+     * @return boolean
+     */
+    public boolean isOperational() {
+       return this.operational;
+    }
+
+    /**
+     * Gets Remove flag.
+     *
+     * @return boolean
+     */
+    public boolean isRemove() {
+       return this.remove;
+    }
+
+    /**
+     * Gets list of {@link PCEPTlv}
+     *
+     * @return List<PCEPTlv>. Can't be null, but may be empty.
+     */
+    public List<PCEPTlv> getTlvs() {
+       return this.tlvs;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (this.delegate ? 1231 : 1237);
+       result = prime * result + this.lspID;
+       result = prime * result + (this.operational ? 1231 : 1237);
+       result = prime * result + (this.remove ? 1231 : 1237);
+       result = prime * result + (this.sync ? 1231 : 1237);
+       result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPLspObject other = (PCEPLspObject) obj;
+       if (this.delegate != other.delegate)
+           return false;
+       if (this.lspID != other.lspID)
+           return false;
+       if (this.operational != other.operational)
+           return false;
+       if (this.remove != other.remove)
+           return false;
+       if (this.sync != other.sync)
+           return false;
+       if (this.tlvs == null) {
+           if (other.tlvs != null)
+               return false;
+       } else if (!this.tlvs.equals(other.tlvs))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("lspID", this.lspID);
+               toStringHelper.add("delegate", this.delegate);
+               toStringHelper.add("sync", this.sync);
+               toStringHelper.add("operational", this.operational);
+               toStringHelper.add("remove", this.remove);
+               toStringHelper.add("tlvs", this.tlvs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPLspaObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPLspaObject.java
new file mode 100644 (file)
index 0000000..3b76b3f
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure for PCEP LSPA Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.11">PCEP LSPA
+ *      Object</a>
+ * @see <a
+ *      href="http://tools.ietf.org/html/rfc3209#section-4.7">SessionAttribute
+ *      Object</a>
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-protection-00#section-4.1">
+ *      The Standby flag in the LSPA object</a>
+ */
+public class PCEPLspaObject extends PCEPObject {
+
+    private final long excludedAny;
+
+    private final long includeAny;
+
+    private final long includeAll;
+
+    private final short setupPriority;
+
+    private final short holdingPriority;
+
+    private final boolean standByPath;
+
+    private final boolean localProtected;
+
+    private final List<PCEPTlv> tlvs;
+
+    /**
+     * Constructs object only with mandatory objects.
+     *
+     * @param excludedAny
+     *            long
+     * @param includeAny
+     *            long
+     * @param includeAll
+     *            long
+     * @param setupPriority
+     *            short
+     * @param holdingPriority
+     *            short
+     * @param standByPath
+     *            boolean
+     * @param localProtected
+     *            boolean
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPLspaObject(long excludedAny, long includeAny, long includeAll, short setupPriority, short holdingPriority, boolean standByPath,
+           boolean localProtected, boolean processed, boolean ignored) {
+       this(excludedAny, includeAny, includeAll, setupPriority, holdingPriority, standByPath, localProtected, null, processed, ignored);
+    }
+
+    /**
+     * Constructs object also with optional objects.
+     *
+     * @param excludedAny
+     *            long
+     * @param includeAny
+     *            long
+     * @param includeAll
+     *            long
+     * @param setupPriority
+     *            short
+     * @param holdingPriority
+     *            short
+     * @param localProtected
+     *            boolean
+     * @param tlvs
+     *            List<PCEPTlv>
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPLspaObject(long excludedAny, long includeAny, long includeAll, short setupPriority, short holdingPriority, boolean standByPath,
+           boolean localProtected, List<PCEPTlv> tlvs, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       this.excludedAny = excludedAny;
+       this.includeAny = includeAny;
+       this.includeAll = includeAll;
+       this.setupPriority = setupPriority;
+       this.holdingPriority = holdingPriority;
+       this.standByPath = standByPath;
+       this.localProtected = localProtected;
+       if (tlvs != null)
+           this.tlvs = tlvs;
+       else
+           this.tlvs = Collections.emptyList();
+    }
+
+    /**
+     * A 32-bit vector representing a set of attribute filters associated with a
+     * tunnel any of which renders a link unacceptable.
+     *
+     * @return long
+     */
+    public long getExcludeAny() {
+       return this.excludedAny;
+    }
+
+    /**
+     * A 32-bit vector representing a set of attribute filters associated with a
+     * tunnel any of which renders a link acceptable (with respect to this
+     * test). A null set (all bits set to zero) automatically passes.
+     *
+     * @return long
+     */
+    public long getIncludeAny() {
+       return this.includeAny;
+    }
+
+    /**
+     * A 32-bit vector representing a set of attribute filters associated with a
+     * tunnel all of which must be present for a link to be acceptable (with
+     * respect to this test). A null set (all bits set to zero) automatically
+     * passes.
+     *
+     * @return long
+     */
+    public long getIncludeAll() {
+       return this.includeAll;
+    }
+
+    /**
+     * The priority of TE LSP with respect to taking resources, in the range of
+     * 0 to 7 (validation not included). The value 0 is the highest priority.
+     * The Setup Priority is used in deciding whether this session can preempt
+     * another session.
+     *
+     * @return short
+     */
+    public short getSetupPriority() {
+       return this.setupPriority;
+    }
+
+    /**
+     * The priority of TE LSP with respect to holding resources, in the range of
+     * 0 to 7 (validation not included). The value 0 is the highest priority.
+     * Holding Priority is used in deciding whether this session can be
+     * preempted by another session.
+     *
+     * @return short
+     */
+    public short getHoldingPriority() {
+       return this.holdingPriority;
+    }
+
+    /**
+     * Corresponds to the "Local Protection Desired" bit ([RFC3209]) of
+     * SESSION-ATTRIBUTE Object. When set, this means that the computed path
+     * must include links protected with Fast REroute as defined in [RFC4090].
+     *
+     * @return boolean
+     */
+    public boolean isLocalProtected() {
+       return this.localProtected;
+    }
+
+    /**
+     * The protection path setup regimen (standby or not) is specified in the
+     * path using a new per-path flag in the LSPA object, the S (standby) flag
+     *
+     * @return boolean
+     */
+    public boolean isStandByPath() {
+       return this.standByPath;
+    }
+
+    /**
+     * Gets list of {@link PCEPTlv}
+     *
+     * @return List<PCEPTlv>. Can't be null, but may be empty.
+     */
+    public List<PCEPTlv> getTlvs() {
+       return this.tlvs;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (int) (this.excludedAny ^ (this.excludedAny >>> 32));
+       result = prime * result + this.holdingPriority;
+       result = prime * result + (int) (this.includeAll ^ (this.includeAll >>> 32));
+       result = prime * result + (int) (this.includeAny ^ (this.includeAny >>> 32));
+       result = prime * result + (this.localProtected ? 1231 : 1237);
+       result = prime * result + this.setupPriority;
+       result = prime * result + (this.standByPath ? 1231 : 1237);
+       result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+       return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (!(obj instanceof PCEPLspaObject))
+           return false;
+       final PCEPLspaObject other = (PCEPLspaObject) obj;
+       if (this.excludedAny != other.excludedAny)
+           return false;
+       if (this.holdingPriority != other.holdingPriority)
+           return false;
+       if (this.includeAll != other.includeAll)
+           return false;
+       if (this.includeAny != other.includeAny)
+           return false;
+       if (this.localProtected != other.localProtected)
+           return false;
+       if (this.setupPriority != other.setupPriority)
+           return false;
+       if (this.standByPath != other.standByPath)
+           return false;
+       if (this.tlvs == null) {
+           if (other.tlvs != null)
+               return false;
+       } else if (!this.tlvs.equals(other.tlvs))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("excludedAny", this.excludedAny);
+               toStringHelper.add("includeAny", this.includeAny);
+               toStringHelper.add("includeAll", this.includeAll);
+               toStringHelper.add("setupPriority", this.setupPriority);
+               toStringHelper.add("holdingPriority", this.holdingPriority);
+               toStringHelper.add("standByPath", this.standByPath);
+               toStringHelper.add("localProtected", this.localProtected);
+               toStringHelper.add("tlvs", this.tlvs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPMetricObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPMetricObject.java
new file mode 100644 (file)
index 0000000..ff0d056
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Metric Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.8">PCEP Metric
+ *      Object</a>
+ */
+public class PCEPMetricObject extends PCEPObject {
+
+    private final boolean bound;
+
+    private final boolean computedMetric;
+
+    private final AbstractMetric<?> metric;
+
+    /**
+     * Constructs PCEP Metric Object.
+     *
+     * @param bound
+     *            boolean
+     * @param computedMetric
+     *            boolean
+     * @param metric
+     *            cannot be null
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPMetricObject(boolean bound, boolean computedMetric, AbstractMetric<?> metric, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       this.bound = bound;
+       this.computedMetric = computedMetric;
+       if (metric == null)
+           throw new IllegalArgumentException("Mandatory parameter metric cannot be null.");
+       this.metric = metric;
+    }
+
+    /**
+     * Gets Bound flag.
+     *
+     * @return boolean
+     */
+    public boolean isBound() {
+       return this.bound;
+    }
+
+    /**
+     * Gets Computed Metric flag.
+     *
+     * @return boolean
+     */
+    public boolean isComputedMetric() {
+       return this.computedMetric;
+    }
+
+    /**
+     * Gets {@link AbstractMetric<?>}.
+     *
+     * @return AbstractMetric<?>
+     */
+    public AbstractMetric<?> getMetric() {
+       return this.metric;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (this.bound ? 1231 : 1237);
+       result = prime * result + (this.computedMetric ? 1231 : 1237);
+       result = prime * result + ((this.metric == null) ? 0 : this.metric.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPMetricObject other = (PCEPMetricObject) obj;
+       if (this.bound != other.bound)
+           return false;
+       if (this.computedMetric != other.computedMetric)
+           return false;
+       if (this.metric == null) {
+           if (other.metric != null)
+               return false;
+       } else if (!this.metric.equals(other.metric))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("bound", this.bound);
+               toStringHelper.add("computedMetric", this.computedMetric);
+               toStringHelper.add("metric", this.metric);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPNoPathObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPNoPathObject.java
new file mode 100644 (file)
index 0000000..df0ec77
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP No Path Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.5">PCEP No Path
+ *      Object</a>
+ */
+public class PCEPNoPathObject extends PCEPObject {
+
+    private final short natureOfIssue;
+
+    private final boolean constrained;
+
+    private final List<PCEPTlv> tlvs;
+
+    /**
+     * Constructs PCEP No Path Object only with mandatory values.
+     *
+     * @param natureOfIssue
+     *            short
+     * @param constrained
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPNoPathObject(short natureOfIssue, boolean constrained, boolean ignored) {
+       this(natureOfIssue, constrained, null, ignored);
+    }
+
+    /**
+     * Constructs PCEP No Path Object also with optional Objects.
+     *
+     * @param natureOfIssue
+     *            short
+     * @param constrained
+     *            boolean
+     * @param tlvs
+     *            List<PCEPTlv>
+     * @param ignored
+     *            boolean
+     */
+    public PCEPNoPathObject(short natureOfIssue, boolean constrained, List<PCEPTlv> tlvs, boolean ignored) {
+       super(false, ignored);
+       this.natureOfIssue = natureOfIssue;
+       this.constrained = constrained;
+       if (tlvs != null)
+           this.tlvs = tlvs;
+       else
+           this.tlvs = Collections.emptyList();
+    }
+
+    /**
+     * Returns short representation of Nature of issue.
+     *
+     * @return short
+     */
+    public short getNatureOfIssue() {
+       return this.natureOfIssue;
+    }
+
+    /**
+     * Gets Constrained flag.
+     *
+     * @return boolean
+     */
+    public boolean isConstrained() {
+       return this.constrained;
+    }
+
+    /**
+     * Gets list of {@link PCEPTlv}
+     *
+     * @return List<PCEPTlv>. Can't be null, but may be empty.
+     */
+    public List<PCEPTlv> getTlvs() {
+       return this.tlvs;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (this.constrained ? 1231 : 1237);
+       result = prime * result + this.natureOfIssue;
+       result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPNoPathObject other = (PCEPNoPathObject) obj;
+       if (this.constrained != other.constrained)
+           return false;
+       if (this.natureOfIssue != other.natureOfIssue)
+           return false;
+       if (this.tlvs == null) {
+           if (other.tlvs != null)
+               return false;
+       } else if (!this.tlvs.equals(other.tlvs))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("natureOfIssue", this.natureOfIssue);
+               toStringHelper.add("constrained", this.constrained);
+               toStringHelper.add("tlvs", this.tlvs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPNonBranchNodeListObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPNonBranchNodeListObject.java
new file mode 100644 (file)
index 0000000..25a2ad3
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Structure of Non-Branch Node list object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc6006#section-3.11.1">Branch Node
+ *      Object [RFC6006]</a>
+ */
+public class PCEPNonBranchNodeListObject extends PCEPBranchNodeObject {
+
+    /**
+     * Constructs Non-Branch Node list object.
+     *
+     * @param subobjects
+     *            List<ExplicitRouteSubobject>
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPNonBranchNodeListObject(List<ExplicitRouteSubobject> subobjects, boolean processed, boolean ignored) {
+       super(subobjects, processed, ignored);
+    }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPNotificationObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPNotificationObject.java
new file mode 100644 (file)
index 0000000..d0a797a
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Notification Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.14">PCEP
+ *      Notification Object</a>
+ */
+public class PCEPNotificationObject extends PCEPObject {
+
+    private final short type;
+
+    private final short value;
+
+    private List<PCEPTlv> tlvs;
+
+    /**
+     * Constructs PCEP Notification Object only with mandatory values.
+     *
+     * @param type
+     *            short
+     * @param value
+     *            short
+     */
+    public PCEPNotificationObject(short type, short value) {
+       this(type, value, null);
+    }
+
+    /**
+     * Constructs PCEP Notification Object also with optional Objects.
+     *
+     * @param type
+     *            short
+     * @param value
+     *            short
+     * @param tlvs
+     *            List<PCEPTlv>
+     */
+    public PCEPNotificationObject(short type, short value, List<PCEPTlv> tlvs) {
+       super(false, false);
+       this.type = type;
+       this.value = value;
+       if (tlvs != null)
+           this.tlvs = tlvs;
+       else
+           this.tlvs = Collections.emptyList();
+    }
+
+    /**
+     * Returns short representation of Type.
+     *
+     * @return short
+     */
+    public short getType() {
+       return this.type;
+    }
+
+    /**
+     * Returns short value.
+     *
+     * @return short
+     */
+    public short getValue() {
+       return this.value;
+    }
+
+    /**
+     * Gets list of {@link PCEPTlv}
+     *
+     * @return List<PCEPTlv>. Can't be null, but may be empty.
+     */
+    public List<PCEPTlv> getTlvs() {
+       return this.tlvs;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+       result = prime * result + this.type;
+       result = prime * result + this.value;
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPNotificationObject other = (PCEPNotificationObject) obj;
+       if (this.tlvs == null) {
+           if (other.tlvs != null)
+               return false;
+       } else if (!this.tlvs.equals(other.tlvs))
+           return false;
+       if (this.type != other.type)
+           return false;
+       if (this.value != other.value)
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("type", this.type);
+               toStringHelper.add("value", this.value);
+               toStringHelper.add("tlvs", this.tlvs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPObjectiveFunctionObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPObjectiveFunctionObject.java
new file mode 100644 (file)
index 0000000..b264d8a
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Indicates the desired/required objective function to be applied by the PCE
+ * during path computation or within a PCRep message so as to indicate the
+ * objective function that was used by the PCE during path computation.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5541#section-3.1">OF Object</a>
+ */
+public class PCEPObjectiveFunctionObject extends PCEPObject {
+
+    private final PCEPOFCodes code;
+
+    private final List<PCEPTlv> tlvs;
+
+    /**
+     * Constructs objective function object only with mandatory objects.
+     *
+     * @param code
+     *            PCEPOFCodes
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPObjectiveFunctionObject(PCEPOFCodes code, boolean processed, boolean ignored) {
+       this(code, null, processed, ignored);
+    }
+
+    /**
+     * Constructs objective function object also with optional objects.
+     *
+     * @param code
+     *            PCEPOFCodes
+     * @param tlvs
+     *            the list of tlvs
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPObjectiveFunctionObject(PCEPOFCodes code, List<PCEPTlv> tlvs, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       this.code = code;
+
+       if (tlvs == null)
+           this.tlvs = Collections.emptyList();
+       else
+           this.tlvs = tlvs;
+    }
+
+    /**
+     * Gets the objective function code
+     *
+     * @return the PCEPOFCodes
+     */
+    public PCEPOFCodes getCode() {
+       return this.code;
+    }
+
+    /**
+     * Gets the list of tlvs
+     *
+     * @return the list of tlvs
+     */
+    public List<PCEPTlv> getTlvs() {
+       return this.tlvs;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("code", this.code);
+               toStringHelper.add("tlvs", this.tlvs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.code == null) ? 0 : this.code.hashCode());
+       result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPObjectiveFunctionObject other = (PCEPObjectiveFunctionObject) obj;
+       if (this.code != other.code)
+           return false;
+       if (this.tlvs == null) {
+           if (other.tlvs != null)
+               return false;
+       } else if (!this.tlvs.equals(other.tlvs))
+           return false;
+       return true;
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPOpenObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPOpenObject.java
new file mode 100644 (file)
index 0000000..799190f
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Open Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.3">PCEP Open
+ *      Object</a>
+ */
+public class PCEPOpenObject extends PCEPObject {
+
+    public static final int PCEP_VERSION = 1;
+
+    private final int keepAliveTimerValue;
+
+    private final int deadTimerValue;
+
+    private final int sessionId;
+
+    private final List<PCEPTlv> tlvs;
+
+    /**
+     * Constructs PCEP Open Object also with optional Objects.
+     *
+     * @param keepAliveTimerValue
+     *            int
+     * @param deadTimerValue
+     *            int
+     * @param sessionId
+     *            int
+     * @param tlvs
+     *            List<PCEPTlv>
+     */
+    public PCEPOpenObject(int keepAliveTimerValue, int deadTimerValue, int sessionId, List<PCEPTlv> tlvs) {
+       super(false, false);
+       this.keepAliveTimerValue = keepAliveTimerValue;
+       this.deadTimerValue = deadTimerValue;
+       this.sessionId = sessionId;
+       if (tlvs != null)
+           this.tlvs = tlvs;
+       else
+           this.tlvs = Collections.emptyList();
+    }
+
+    /**
+     * Constructs PCEP Open Object only with mandatory values.
+     *
+     * @param keepAliveTimerValue
+     *            int
+     * @param deadTimerValue
+     *            int
+     * @param sessionId
+     *            int
+     */
+    public PCEPOpenObject(int keepAliveTimerValue, int deadTimerValue, int sessionId) {
+       this(keepAliveTimerValue, deadTimerValue, sessionId, Collections.<PCEPTlv> emptyList());
+    }
+
+    /**
+     * Returns integer representation of Keep Alive Timer.
+     *
+     * @return int
+     */
+    public int getKeepAliveTimerValue() {
+       return this.keepAliveTimerValue;
+    }
+
+    /**
+     * Returns integer representation of Dead Timer.
+     *
+     * @return int
+     */
+    public int getDeadTimerValue() {
+       return this.deadTimerValue;
+    }
+
+    /**
+     * Returns integer representation of Session ID.
+     *
+     * @return int
+     */
+    public int getSessionId() {
+       return this.sessionId;
+    }
+
+    /**
+     * Gets list of {@link PCEPTlv}.
+     *
+     * @return List<PCEPTlv>
+     */
+    public List<PCEPTlv> getTlvs() {
+       return this.tlvs;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + this.deadTimerValue;
+       result = prime * result + this.keepAliveTimerValue;
+       result = prime * result + this.sessionId;
+       result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPOpenObject other = (PCEPOpenObject) obj;
+       if (this.deadTimerValue != other.deadTimerValue)
+           return false;
+       if (this.keepAliveTimerValue != other.keepAliveTimerValue)
+           return false;
+       if (this.sessionId != other.sessionId)
+           return false;
+       if (this.tlvs == null) {
+           if (other.tlvs != null)
+               return false;
+       } else if (!this.tlvs.equals(other.tlvs))
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("keepAliveTimerValue", this.keepAliveTimerValue);
+               toStringHelper.add("deadTimerValue", this.deadTimerValue);
+               toStringHelper.add("sessionId", this.sessionId);
+               toStringHelper.add("tlvs", this.tlvs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPP2MPEndPointsObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPP2MPEndPointsObject.java
new file mode 100644 (file)
index 0000000..af20d8c
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Objects.ToStringHelper;
+
+public class PCEPP2MPEndPointsObject<T extends NetworkAddress<T>> extends PCEPEndPoints {
+
+    private final long leafType;
+
+    private final T sourceAddress;
+
+    private final List<T> destinationAddresses;
+
+    public PCEPP2MPEndPointsObject(long leafType, T sourceAddress, List<T> destinationAddresses, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       this.leafType = leafType;
+       this.sourceAddress = sourceAddress;
+       if (destinationAddresses == null || destinationAddresses.isEmpty())
+           throw new IllegalArgumentException("At least one destination have to be specified.");
+
+       this.destinationAddresses = destinationAddresses;
+    }
+
+    /**
+     * @return the leafType
+     */
+    public long getLeafType() {
+       return this.leafType;
+    }
+
+    /**
+     * @return the sourceAddress
+     */
+    public T getSourceAddress() {
+       return this.sourceAddress;
+    }
+
+    /**
+     * @return the destinationAddresses
+     */
+    public List<T> getDestinationAddresses() {
+       return this.destinationAddresses;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.destinationAddresses == null) ? 0 : this.destinationAddresses.hashCode());
+       result = prime * result + (int) (this.leafType ^ (this.leafType >>> 32));
+       result = prime * result + ((this.sourceAddress == null) ? 0 : this.sourceAddress.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPP2MPEndPointsObject<?> other = (PCEPP2MPEndPointsObject<?>) obj;
+       if (this.destinationAddresses == null) {
+           if (other.destinationAddresses != null)
+               return false;
+       } else if (!this.destinationAddresses.equals(other.destinationAddresses))
+           return false;
+       if (this.leafType != other.leafType)
+           return false;
+       if (this.sourceAddress == null) {
+           if (other.sourceAddress != null)
+               return false;
+       } else if (!this.sourceAddress.equals(other.sourceAddress))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("leafType", this.leafType);
+               toStringHelper.add("sourceAddress", this.sourceAddress);
+               toStringHelper.add("destinationAddresses", this.destinationAddresses);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPReportedRouteObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPReportedRouteObject.java
new file mode 100644 (file)
index 0000000..25dbdc1
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Reported Route Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.10">PCEP Reported
+ *      Route Object</a>
+ */
+public class PCEPReportedRouteObject extends PCEPObject {
+
+    private final List<ReportedRouteSubobject> subobjects;
+
+    /**
+     * Constructs PCEP Reported Route Object.
+     *
+     * @param subobjects
+     *            List<ReportedRouteSubobject>. Can't be null or empty.
+     * @param processed
+     *            boolean
+     */
+    public PCEPReportedRouteObject(List<ReportedRouteSubobject> subobjects, boolean processed) {
+       super(processed, false);
+       if (subobjects == null || subobjects.isEmpty())
+           throw new IllegalArgumentException("Subobjects can't be null or empty.");
+       this.subobjects = subobjects;
+    }
+
+    /**
+     * Gets list of {@link ReportedRouteSubobject}.
+     *
+     * @return List<PCEPSubobject>. Can't be null or empty.
+     */
+    public List<ReportedRouteSubobject> getSubobjects() {
+       return this.subobjects;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("subobjects", this.subobjects);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPReportedRouteObject other = (PCEPReportedRouteObject) obj;
+       if (this.subobjects == null) {
+           if (other.subobjects != null)
+               return false;
+       } else if (!this.subobjects.equals(other.subobjects))
+           return false;
+       return true;
+    }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPRequestParameterObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPRequestParameterObject.java
new file mode 100644 (file)
index 0000000..650dc68
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.tlv.OrderTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Requested Parameter Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.4">PCEP Request
+ *      Parameter Object [RFC5440]</a>
+ * @see <a href="http://tools.ietf.org/html/rfc5541#section-6.2.4">RP Object
+ *      Flag [RFC5541]</a>
+ * @see <a href="http://tools.ietf.org/html/rfc6006#section-3.3.1">The Extension
+ *      of the RP Object [RFC6006]</a>
+ */
+public class PCEPRequestParameterObject extends PCEPObject {
+
+    private final boolean loose;
+
+    private final boolean bidirectional;
+
+    private final boolean reoptimized;
+
+    private final boolean makeBeforeBreak;
+
+    private final boolean reportRequestOrder;
+
+    private final boolean suplyOFOnResponse;
+
+    /*
+     * RFC6006 flags
+     */
+    private final boolean fragmentation;
+
+    private final boolean p2mp;
+
+    private final boolean eroCompression;
+
+    // End of flags
+
+    private final short priority;
+
+    private final long requestID;
+
+    private final List<PCEPTlv> tlvs;
+
+    /**
+     * Constructs PCEP Requested Parameter Object only with mandatory values.
+     *
+     * @param loose
+     *            boolean
+     * @param bidirectional
+     *            boolean
+     * @param reoptimized
+     *            boolean
+     * @param makeBeforeBreak
+     *            boolean
+     * @param suplyOFOnResponse
+     *            boolean
+     * @param priority
+     *            short
+     * @param requestID
+     *            long
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean;
+     */
+    public PCEPRequestParameterObject(boolean loose, boolean bidirectional, boolean reoptimized, boolean makeBeforeBreak, boolean suplyOFOnResponse,
+           boolean fragmentation, boolean p2mp, boolean eroCompression, short priority, long requestID, boolean processed, boolean ignored) {
+       this(loose, bidirectional, reoptimized, makeBeforeBreak, false, suplyOFOnResponse, fragmentation, p2mp, eroCompression, priority, requestID, null,
+               processed, ignored);
+    }
+
+    /**
+     * Constructs PCEP Requested Parameter Object also with optional Objects.
+     *
+     * @param loose
+     *            boolean
+     * @param bidirectional
+     *            boolean
+     * @param reoptimized
+     *            boolean
+     * @param makeBeforeBreak
+     *            boolean
+     * @param reportRequestOrder
+     *            boolean
+     * @param suplyOFOnResponse
+     *            boolean
+     * @param priority
+     *            short
+     * @param requestID
+     *            long
+     * @param tlvs
+     *            List<PCEPTlv>
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPRequestParameterObject(boolean loose, boolean bidirectional, boolean reoptimized, boolean makeBeforeBreak, boolean reportRequestOrder,
+           boolean suplyOFOnResponse, boolean fragmentation, boolean p2mp, boolean eroCompression, short priority, long requestID, List<PCEPTlv> tlvs,
+           boolean processed, boolean ignored) {
+       super(processed, ignored);
+       this.loose = loose;
+       this.bidirectional = bidirectional;
+       this.reoptimized = reoptimized;
+       this.makeBeforeBreak = makeBeforeBreak;
+       this.reportRequestOrder = reportRequestOrder;
+       this.suplyOFOnResponse = suplyOFOnResponse;
+       this.fragmentation = fragmentation;
+       this.p2mp = p2mp;
+       this.eroCompression = eroCompression;
+
+       this.priority = priority;
+       this.requestID = requestID;
+       if (tlvs != null)
+           this.tlvs = tlvs;
+       else
+           this.tlvs = Collections.emptyList();
+
+       if (makeBeforeBreak && !reoptimized)
+           throw new IllegalArgumentException("M (make-before-break) can be set only if R (reoptimied) flag is set too.");
+
+       if (reportRequestOrder && !this.validateOrderTlv())
+           throw new IllegalArgumentException("D (report request order) flag is set, but missing OrderTlv.");
+    }
+
+    /**
+     * Gets Loose flag.
+     *
+     * @return boolean
+     */
+    public boolean isLoose() {
+       return this.loose;
+    }
+
+    /**
+     * Gets Bidirectional flag.
+     *
+     * @return boolean
+     */
+    public boolean isBidirectional() {
+       return this.bidirectional;
+    }
+
+    /**
+     * Gets Reoptimization flag.
+     *
+     * @return boolean
+     */
+    public boolean isReoptimized() {
+       return this.reoptimized;
+    }
+
+    /**
+     * Gets make-before-break flag
+     *
+     * @return boolean
+     */
+    public boolean isMakeBeforeBreak() {
+       return this.makeBeforeBreak;
+    }
+
+    /**
+     * Gets report requested order flag
+     *
+     * @return boolean
+     */
+    public boolean isReportRequestOrder() {
+       return this.reportRequestOrder;
+    }
+
+    /**
+     * Gets report supply objective function on response flag
+     *
+     * @return boolean
+     */
+    public boolean isSuplyOFOnResponse() {
+       return this.suplyOFOnResponse;
+    }
+
+    /**
+     * @return the fragmentation
+     */
+    public boolean isFragmentation() {
+       return this.fragmentation;
+    }
+
+    /**
+     * @return the p2mp
+     */
+    public boolean isP2mp() {
+       return this.p2mp;
+    }
+
+    /**
+     * @return the eroCompression
+     */
+    public boolean isEroCompression() {
+       return this.eroCompression;
+    }
+
+    /**
+     * Returns short representation of Priority.
+     *
+     * @return short
+     */
+    public short getPriority() {
+       return this.priority;
+    }
+
+    /**
+     * Returns long representation of Requested ID.
+     *
+     * @return long
+     */
+    public long getRequestID() {
+       return this.requestID;
+    }
+
+    /**
+     * Gets list of {@link PCEPTlv}
+     *
+     * @return List<PCEPTlv>. Can't be null, but may be empty.
+     */
+    public List<PCEPTlv> getTlvs() {
+       return this.tlvs;
+    }
+
+    private boolean validateOrderTlv() {
+       for (final PCEPTlv tlv : this.tlvs) {
+           if (tlv instanceof OrderTlv)
+               return true;
+       }
+
+       return false;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (this.bidirectional ? 1231 : 1237);
+       result = prime * result + (this.eroCompression ? 1231 : 1237);
+       result = prime * result + (this.fragmentation ? 1231 : 1237);
+       result = prime * result + (this.loose ? 1231 : 1237);
+       result = prime * result + (this.makeBeforeBreak ? 1231 : 1237);
+       result = prime * result + (this.p2mp ? 1231 : 1237);
+       result = prime * result + this.priority;
+       result = prime * result + (this.reoptimized ? 1231 : 1237);
+       result = prime * result + (this.reportRequestOrder ? 1231 : 1237);
+       result = prime * result + (int) (this.requestID ^ (this.requestID >>> 32));
+       result = prime * result + (this.suplyOFOnResponse ? 1231 : 1237);
+       result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPRequestParameterObject other = (PCEPRequestParameterObject) obj;
+       if (this.bidirectional != other.bidirectional)
+           return false;
+       if (this.eroCompression != other.eroCompression)
+           return false;
+       if (this.fragmentation != other.fragmentation)
+           return false;
+       if (this.loose != other.loose)
+           return false;
+       if (this.makeBeforeBreak != other.makeBeforeBreak)
+           return false;
+       if (this.p2mp != other.p2mp)
+           return false;
+       if (this.priority != other.priority)
+           return false;
+       if (this.reoptimized != other.reoptimized)
+           return false;
+       if (this.reportRequestOrder != other.reportRequestOrder)
+           return false;
+       if (this.requestID != other.requestID)
+           return false;
+       if (this.suplyOFOnResponse != other.suplyOFOnResponse)
+           return false;
+       if (this.tlvs == null) {
+           if (other.tlvs != null)
+               return false;
+       } else if (!this.tlvs.equals(other.tlvs))
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("loose", this.loose);
+               toStringHelper.add("bidirectional", this.bidirectional);
+               toStringHelper.add("reoptimized", this.reoptimized);
+               toStringHelper.add("makeBeforeBreak", this.makeBeforeBreak);
+               toStringHelper.add("reportRequestOrder", this.reportRequestOrder);
+               toStringHelper.add("suplyOFOnResponse", this.suplyOFOnResponse);
+               toStringHelper.add("fragmentation", this.fragmentation);
+               toStringHelper.add("p2mp", this.p2mp);
+               toStringHelper.add("eroCompression", this.eroCompression);
+               toStringHelper.add("priority", this.priority);
+               toStringHelper.add("requestID", this.requestID);
+               toStringHelper.add("tlvs", this.tlvs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPRequestedPathBandwidthObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPRequestedPathBandwidthObject.java
new file mode 100644 (file)
index 0000000..f2ad8bf
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+
+/**
+ * Structure of specific Bandwidth. Used for example in Composite Requested
+ * Object to request specific bandwidth.
+ */
+public class PCEPRequestedPathBandwidthObject extends PCEPBandwidthObject {
+
+    /**
+     * Constructs Requested Path Bandwidth.
+     *
+     * @param bandwidth
+     *            Bandwidth. Can't be null.
+     * @param processed
+     *            boolean
+     * @param ignored
+     *            boolean
+     */
+    public PCEPRequestedPathBandwidthObject(Bandwidth bandwidth, boolean processed, boolean ignored) {
+       super(bandwidth, processed, ignored);
+    }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPSecondaryExplicitRouteObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPSecondaryExplicitRouteObject.java
new file mode 100644 (file)
index 0000000..f3e8861
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * @author miroslav
+ *
+ *         May 2012
+ *
+ *         Copyright (c) 2012 by Cisco Systems, Inc. All rights reserved.
+ */
+
+public class PCEPSecondaryExplicitRouteObject extends PCEPObject {
+
+    private final List<ExplicitRouteSubobject> subobjects;
+
+    /**
+     * Constructs Secondary Explicit Route Object.
+     *
+     * @param subobjects
+     *            List<ExplicitRouteSubobject>. Can't be null or empty.
+     * @param ignored
+     *            boolean
+     */
+    public PCEPSecondaryExplicitRouteObject(List<ExplicitRouteSubobject> subobjects, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       if (subobjects == null || subobjects.isEmpty())
+           throw new IllegalArgumentException("Subobjects can't be null or empty.");
+       this.subobjects = subobjects;
+    }
+
+    /**
+     * Gets list of {@link ExplicitRouteSubobject}
+     *
+     * @return List<ExplicitRouteSubobject>. Can't be null or empty.
+     */
+    public List<ExplicitRouteSubobject> getSubobjects() {
+       return this.subobjects;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("subobjects", this.subobjects);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPSecondaryExplicitRouteObject other = (PCEPSecondaryExplicitRouteObject) obj;
+       if (this.subobjects == null) {
+           if (other.subobjects != null)
+               return false;
+       } else if (!this.subobjects.equals(other.subobjects))
+           return false;
+       return true;
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPSecondaryRecordRouteObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPSecondaryRecordRouteObject.java
new file mode 100644 (file)
index 0000000..69d6cd2
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+public class PCEPSecondaryRecordRouteObject extends PCEPObject {
+
+    private final List<ReportedRouteSubobject> subobjects;
+
+    /**
+     * Constructs Secondary Record Route Object.
+     *
+     * @param subobjects
+     *            List<ReportedRouteSubobject>. Can't be null or empty.
+     * @param ignored
+     *            boolean
+     */
+    public PCEPSecondaryRecordRouteObject(List<ReportedRouteSubobject> subobjects, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       if (subobjects == null || subobjects.isEmpty())
+           throw new IllegalArgumentException("Subobjects can't be null or empty.");
+       this.subobjects = subobjects;
+    }
+
+    /**
+     * Gets list of {@link ReportedRouteSubobject}
+     *
+     * @return List<ReportedRouteSubobject>. Can't be null or empty.
+     */
+    public List<ReportedRouteSubobject> getSubobjects() {
+       return this.subobjects;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("subobjects", this.subobjects);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPSecondaryRecordRouteObject other = (PCEPSecondaryRecordRouteObject) obj;
+       if (this.subobjects == null) {
+           if (other.subobjects != null)
+               return false;
+       } else if (!this.subobjects.equals(other.subobjects))
+           return false;
+       return true;
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPSvecObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPSvecObject.java
new file mode 100644 (file)
index 0000000..4a618eb
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP SVEC Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.13">PCEP SVEC
+ *      Object</a>
+ * @see <a
+ *      href="http://tools.ietf.org/html/rfc6006#section-3.12">Synchronization
+ *      of P2MP TE Path Computation Requests [RFC6006]</a>
+ */
+public class PCEPSvecObject extends PCEPObject {
+
+    private final boolean linkDiversed;
+
+    private final boolean nodeDiversed;
+
+    private final boolean srlgDiversed;
+
+    private final boolean paritialPathDiversed;
+
+    private final boolean linkDirectionDiversed;
+
+    private final List<Long> requestIDs;
+
+    /**
+     * Constructs PCEP SVEC Object.
+     *
+     * @param linkDiversed
+     *            boolean
+     * @param nodeDiversed
+     *            boolean
+     * @param srlgDiversed
+     *            boolean
+     * @param requestIDs
+     *            List<Long>. Can't be null or empty.
+     * @param processed
+     *            boolean
+     */
+    public PCEPSvecObject(boolean linkDiversed, boolean nodeDiversed, boolean srlgDiversed, boolean partialPathDiversed, boolean linkDirectionDiversed,
+           List<Long> requestIDs, boolean processed) {
+       super(processed, false);
+       this.linkDiversed = linkDiversed;
+       this.nodeDiversed = nodeDiversed;
+       this.srlgDiversed = srlgDiversed;
+       this.paritialPathDiversed = partialPathDiversed;
+       this.linkDirectionDiversed = linkDirectionDiversed;
+
+       if (requestIDs == null || requestIDs.isEmpty())
+           throw new IllegalArgumentException("RequestIDs can't be null or empty.");
+       this.requestIDs = requestIDs;
+    }
+
+    /**
+     * Gets Link Diversed flag.
+     *
+     * @return boolean
+     */
+    public boolean isLinkDiversed() {
+       return this.linkDiversed;
+    }
+
+    /**
+     * Gets Node Diversed flag.
+     *
+     * @return boolean
+     */
+    public boolean isNodeDiversed() {
+       return this.nodeDiversed;
+    }
+
+    /**
+     * Gets Srlg Diversed flag.
+     *
+     * @return boolean
+     */
+    public boolean isSrlgDiversed() {
+       return this.srlgDiversed;
+    }
+
+    public boolean isParitialPathDiversed() {
+       return this.paritialPathDiversed;
+    }
+
+    public boolean isLinkDirectionDiversed() {
+       return this.linkDirectionDiversed;
+    }
+
+    /**
+     * Gets list of Long representations of RequestIDs.
+     *
+     * @return List<Long>. Can't be null or empty.
+     */
+    public List<Long> getRequestIDs() {
+       return this.requestIDs;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (this.linkDiversed ? 1231 : 1237);
+       result = prime * result + (this.nodeDiversed ? 1231 : 1237);
+       result = prime * result + ((this.requestIDs == null) ? 0 : this.requestIDs.hashCode());
+       result = prime * result + (this.srlgDiversed ? 1231 : 1237);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPSvecObject other = (PCEPSvecObject) obj;
+       if (this.linkDiversed != other.linkDiversed)
+           return false;
+       if (this.nodeDiversed != other.nodeDiversed)
+           return false;
+       if (this.requestIDs == null) {
+           if (other.requestIDs != null)
+               return false;
+       } else if (!this.requestIDs.equals(other.requestIDs))
+           return false;
+       if (this.srlgDiversed != other.srlgDiversed)
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("linkDiversed", this.linkDiversed);
+               toStringHelper.add("nodeDiversed", this.nodeDiversed);
+               toStringHelper.add("srlgDiversed", this.srlgDiversed);
+               toStringHelper.add("paritialPathDiversed", this.paritialPathDiversed);
+               toStringHelper.add("linkDirectionDiversed", this.linkDirectionDiversed);
+               toStringHelper.add("requestIDs", this.requestIDs);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPUnreachedDestinationObject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/object/PCEPUnreachedDestinationObject.java
new file mode 100644 (file)
index 0000000..37b6d8c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+public class PCEPUnreachedDestinationObject<T extends NetworkAddress<T>> extends PCEPObject {
+
+    private final List<T> unreachedDestinations;
+
+    public PCEPUnreachedDestinationObject(List<T> unreachedDestinations, boolean processed, boolean ignored) {
+       super(processed, ignored);
+       if (unreachedDestinations == null || unreachedDestinations.isEmpty())
+           throw new IllegalArgumentException("At least one destination have to be specified.");
+
+       this.unreachedDestinations = unreachedDestinations;
+    }
+
+    public List<T> getUnreachedDestinations() {
+       return this.unreachedDestinations;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.unreachedDestinations == null) ? 0 : this.unreachedDestinations.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final PCEPUnreachedDestinationObject<?> other = (PCEPUnreachedDestinationObject<?>) obj;
+       if (this.unreachedDestinations == null) {
+           if (other.unreachedDestinations != null)
+               return false;
+       } else if (!this.unreachedDestinations.equals(other.unreachedDestinations))
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("unreachedDestinations", this.unreachedDestinations);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROAsNumberSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROAsNumberSubobject.java
new file mode 100644 (file)
index 0000000..5e04c8d
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Autonomous System Number Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.3.3.4">Section
+ *      4.3.3.4.: Subobject 32: Autonomous System Number</a>
+ */
+public class EROAsNumberSubobject extends ExplicitRouteSubobject {
+
+       private final ASNumber asnumber;
+
+       /**
+        * Constructs new ASNumber Subobject.
+        *
+        * @param asnumber
+        *            ASNumber
+        * @param loose
+        *            boolean
+        */
+       public EROAsNumberSubobject(ASNumber asnumber, boolean loose) {
+               super(loose);
+               this.asnumber = asnumber;
+       }
+
+       /**
+        * Gets {@link ASNumber}.
+        *
+        * @return ASNumber
+        */
+       public ASNumber getASNumber() {
+               return this.asnumber;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.asnumber == null) ? 0 : this.asnumber.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final EROAsNumberSubobject other = (EROAsNumberSubobject) obj;
+               if (this.asnumber == null) {
+                       if (other.asnumber != null)
+                               return false;
+               } else if (!this.asnumber.equals(other.asnumber))
+                       return false;
+               return true;
+       }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("asnumber", this.asnumber);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROExplicitExclusionRouteSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROExplicitExclusionRouteSubobject.java
new file mode 100644 (file)
index 0000000..a9515fe
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.subobject;
+
+import java.util.List;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class EROExplicitExclusionRouteSubobject extends ExplicitRouteSubobject {
+    private final List<ExcludeRouteSubobject> xroSubobjets;
+
+    public EROExplicitExclusionRouteSubobject(List<ExcludeRouteSubobject> xroSubobjets) {
+       super();
+       this.xroSubobjets = xroSubobjets;
+    }
+
+    public List<ExcludeRouteSubobject> getXroSubobjets() {
+       return this.xroSubobjets;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + ((this.xroSubobjets == null) ? 0 : this.xroSubobjets.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final EROExplicitExclusionRouteSubobject other = (EROExplicitExclusionRouteSubobject) obj;
+       if (this.xroSubobjets == null) {
+           if (other.xroSubobjets != null)
+               return false;
+       } else if (!this.xroSubobjets.equals(other.xroSubobjets))
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("xroSubobjets", this.xroSubobjets);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROGeneralizedLabelSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROGeneralizedLabelSubobject.java
new file mode 100644 (file)
index 0000000..f9c9b4a
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Generalized Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3471#section-3.2">3.2.
+ *      Generalized Label</a>
+ */
+public class EROGeneralizedLabelSubobject extends EROLabelSubobject {
+
+    private final byte[] label;
+
+    public EROGeneralizedLabelSubobject(byte[] label, boolean upStream, boolean loose) {
+       super(upStream);
+
+       if (label.length % 4 != 0)
+           throw new IllegalArgumentException("Length of label is not multiple of 4.");
+
+       this.label = label;
+    }
+
+    public byte[] getLabel() {
+       return this.label;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + Arrays.hashCode(this.label);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final EROGeneralizedLabelSubobject other = (EROGeneralizedLabelSubobject) obj;
+       if (!Arrays.equals(this.label, other.label))
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("label", this.label);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROIPPrefixSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROIPPrefixSubobject.java
new file mode 100644 (file)
index 0000000..ef8a324
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.Prefix;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Parametrized structure of IP Prefix Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.3.3.2">Section
+ *      4.3.3.2.: Subobject 1: IPv4 prefix</a> and <a
+ *      href="http://tools.ietf.org/html/rfc3209#section-4.3.3.3">Section
+ *      4.3.3.2.: Subobject 2: IPv6 prefix</a>
+ *
+ * @param <T>
+ *            subtype of Prefix
+ */
+public class EROIPPrefixSubobject<T extends Prefix<?>> extends ExplicitRouteSubobject {
+
+       private final T prefix;
+
+       /**
+        * Constructs IPPrefix Subobject.
+        *
+        * @param prefix
+        *            T
+        * @param loose
+        *            boolean
+        */
+       public EROIPPrefixSubobject(T prefix, boolean loose) {
+               super(loose);
+               this.prefix = prefix;
+       }
+
+       /**
+        * Gets specific {@link Prefix}.
+        *
+        * @return prefix T
+        */
+       public T getPrefix() {
+               return this.prefix;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.prefix == null) ? 0 : this.prefix.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final EROIPPrefixSubobject<?> other = (EROIPPrefixSubobject<?>) obj;
+               if (this.prefix == null) {
+                       if (other.prefix != null)
+                               return false;
+               } else if (!this.prefix.equals(other.prefix))
+                       return false;
+               return true;
+       }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("prefix", this.prefix);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROLabelSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROLabelSubobject.java
new file mode 100644 (file)
index 0000000..e2712ca
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Label subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3473#section-5.1">Label ERO
+ *      subobject</a>
+ */
+
+public abstract class EROLabelSubobject extends ExplicitRouteSubobject {
+
+    private final boolean upStream;
+
+    /**
+     * Constructs new Label subobject.
+     *
+     * @param upStream
+     *            if set label is upstream
+     * @param label
+     *            Label
+     * @param loose
+     *            boolean
+     */
+    public EROLabelSubobject(boolean upStream) {
+       super(false);
+       this.upStream = upStream;
+    }
+
+    public boolean isUpStream() {
+       return this.upStream;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (this.upStream ? 1231 : 1237);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final EROLabelSubobject other = (EROLabelSubobject) obj;
+       if (this.upStream != other.upStream)
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("upStream", this.upStream);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROPathKeyWith128PCEIDSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROPathKeyWith128PCEIDSubobject.java
new file mode 100644 (file)
index 0000000..1efb310
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class EROPathKeyWith128PCEIDSubobject extends ExplicitRouteSubobject {
+
+    private final int pathKey;
+
+    private final byte[] pceId;
+
+    public EROPathKeyWith128PCEIDSubobject(int pathKey, byte[] pceId, boolean loose) {
+       super(loose);
+       this.pathKey = pathKey;
+       if (pceId == null)
+           throw new IllegalArgumentException("PCE ID can't be null.");
+
+       if (pceId.length != 16)
+           throw new IllegalArgumentException("PCE ID is not 16 bytes long.");
+
+       this.pceId = pceId;
+    }
+
+    public int getPathKey() {
+       return this.pathKey;
+    }
+
+    public byte[] getPceId() {
+       return this.pceId;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + this.pathKey;
+       result = prime * result + Arrays.hashCode(this.pceId);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final EROPathKeyWith128PCEIDSubobject other = (EROPathKeyWith128PCEIDSubobject) obj;
+       if (this.pathKey != other.pathKey)
+           return false;
+       if (!Arrays.equals(this.pceId, other.pceId))
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("pathKey", this.pathKey);
+               toStringHelper.add("pceId", this.pceId);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROPathKeyWith32PCEIDSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROPathKeyWith32PCEIDSubobject.java
new file mode 100644 (file)
index 0000000..d2976cb
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class EROPathKeyWith32PCEIDSubobject extends ExplicitRouteSubobject {
+
+    private final int pathKey;
+
+    private final byte[] pceId;
+
+    public EROPathKeyWith32PCEIDSubobject(int pathKey, byte[] pceId, boolean loose) {
+       super(loose);
+       this.pathKey = pathKey;
+       if (pceId == null)
+           throw new IllegalArgumentException("PCE ID can't be null.");
+
+       if (pceId.length != 4)
+           throw new IllegalArgumentException("PCE ID is not 4 bytes long.");
+
+       this.pceId = pceId;
+    }
+
+    public int getPathKey() {
+       return this.pathKey;
+    }
+
+    public byte[] getPceId() {
+       return this.pceId;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + this.pathKey;
+       result = prime * result + Arrays.hashCode(this.pceId);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final EROPathKeyWith32PCEIDSubobject other = (EROPathKeyWith32PCEIDSubobject) obj;
+       if (this.pathKey != other.pathKey)
+           return false;
+       if (!Arrays.equals(this.pceId, other.pceId))
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("pathKey", this.pathKey);
+               toStringHelper.add("pceId", this.pceId);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROProtectionSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROProtectionSubobject.java
new file mode 100644 (file)
index 0000000..d74138a
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+public abstract class EROProtectionSubobject extends ExplicitRouteSubobject {
+    public EROProtectionSubobject(boolean loose) {
+       super(loose);
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROProtectionType1Subobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROProtectionType1Subobject.java
new file mode 100644 (file)
index 0000000..e3f5cef
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class EROProtectionType1Subobject extends EROProtectionSubobject {
+
+    private final boolean secondary;
+
+    private final byte linkFlags;
+
+    /**
+     * @param secondary
+     * @param linkFlags
+     */
+    public EROProtectionType1Subobject(boolean secondary, byte linkFlags, boolean loose) {
+       super(loose);
+       this.secondary = secondary;
+       this.linkFlags = linkFlags;
+    }
+
+    /**
+     * @return the secondary
+     */
+    public boolean isSecondary() {
+       return this.secondary;
+    }
+
+    /**
+     * @return the linkFlags
+     */
+    public byte getLinkFlags() {
+       return this.linkFlags;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + this.linkFlags;
+       result = prime * result + (this.secondary ? 1231 : 1237);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final EROProtectionType1Subobject other = (EROProtectionType1Subobject) obj;
+       if (this.linkFlags != other.linkFlags)
+           return false;
+       if (this.secondary != other.secondary)
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("secondary", this.secondary);
+               toStringHelper.add("linkFlags", this.linkFlags);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROProtectionType2Subobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROProtectionType2Subobject.java
new file mode 100644 (file)
index 0000000..4e893e1
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class EROProtectionType2Subobject extends EROProtectionSubobject {
+    private final boolean secondaryLsp;
+
+    private final boolean protectionLsp;
+
+    private final boolean notification;
+
+    private final boolean operational;
+
+    private final byte lspFlags;
+
+    private final byte linkFlags;
+
+    private final boolean inPlace;
+
+    private final boolean required;
+
+    private final byte segFlags;
+
+    /**
+     * @param secondaryLsp
+     * @param protectionLsp
+     * @param notification
+     * @param operational
+     * @param lspFlags
+     * @param linkFlags
+     * @param inPlace
+     * @param required
+     * @param segFlags
+     */
+    public EROProtectionType2Subobject(boolean secondaryLsp, boolean protectionLsp, boolean notification, boolean operational, byte lspFlags, byte linkFlags,
+           boolean inPlace, boolean required, byte segFlags, boolean loose) {
+       super(loose);
+       this.secondaryLsp = secondaryLsp;
+       this.protectionLsp = protectionLsp;
+       this.notification = notification;
+       this.operational = operational;
+       this.lspFlags = lspFlags;
+       this.linkFlags = linkFlags;
+       this.inPlace = inPlace;
+       this.required = required;
+       this.segFlags = segFlags;
+    }
+
+    /**
+     * @return the secondaryLsp
+     */
+    public boolean isSecondaryLsp() {
+       return this.secondaryLsp;
+    }
+
+    /**
+     * @return the protectionLsp
+     */
+    public boolean isProtectionLsp() {
+       return this.protectionLsp;
+    }
+
+    /**
+     * @return the notification
+     */
+    public boolean isNotification() {
+       return this.notification;
+    }
+
+    /**
+     * @return the operational
+     */
+    public boolean isOperational() {
+       return this.operational;
+    }
+
+    /**
+     * @return the lspFlags
+     */
+    public byte getLspFlags() {
+       return this.lspFlags;
+    }
+
+    /**
+     * @return the linkFlags
+     */
+    public byte getLinkFlags() {
+       return this.linkFlags;
+    }
+
+    /**
+     * @return the inPlace
+     */
+    public boolean isInPlace() {
+       return this.inPlace;
+    }
+
+    /**
+     * @return the required
+     */
+    public boolean isRequired() {
+       return this.required;
+    }
+
+    /**
+     * @return the segFlags
+     */
+    public byte getSegFlags() {
+       return this.segFlags;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (this.inPlace ? 1231 : 1237);
+       result = prime * result + this.linkFlags;
+       result = prime * result + this.lspFlags;
+       result = prime * result + (this.notification ? 1231 : 1237);
+       result = prime * result + (this.operational ? 1231 : 1237);
+       result = prime * result + (this.protectionLsp ? 1231 : 1237);
+       result = prime * result + (this.required ? 1231 : 1237);
+       result = prime * result + (this.secondaryLsp ? 1231 : 1237);
+       result = prime * result + this.segFlags;
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final EROProtectionType2Subobject other = (EROProtectionType2Subobject) obj;
+       if (this.inPlace != other.inPlace)
+           return false;
+       if (this.linkFlags != other.linkFlags)
+           return false;
+       if (this.lspFlags != other.lspFlags)
+           return false;
+       if (this.notification != other.notification)
+           return false;
+       if (this.operational != other.operational)
+           return false;
+       if (this.protectionLsp != other.protectionLsp)
+           return false;
+       if (this.required != other.required)
+           return false;
+       if (this.secondaryLsp != other.secondaryLsp)
+           return false;
+       if (this.segFlags != other.segFlags)
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("secondaryLsp", this.secondaryLsp);
+               toStringHelper.add("protectionLsp", this.protectionLsp);
+               toStringHelper.add("notification", this.notification);
+               toStringHelper.add("operational", this.operational);
+               toStringHelper.add("lspFlags", this.lspFlags);
+               toStringHelper.add("linkFlags", this.linkFlags);
+               toStringHelper.add("inPlace", this.inPlace);
+               toStringHelper.add("required", this.required);
+               toStringHelper.add("segFlags", this.segFlags);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROType1LabelSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROType1LabelSubobject.java
new file mode 100644 (file)
index 0000000..926791a
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Type 1 Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.1">4.1. Label
+ *      Object</a>
+ */
+public class EROType1LabelSubobject extends EROLabelSubobject {
+
+    private final long label;
+
+    public EROType1LabelSubobject(long label, boolean upStream, boolean loose) {
+       super(upStream);
+       this.label = label;
+    }
+
+    public long getLabel() {
+       return this.label;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (int) (this.label ^ (this.label >>> 32));
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final EROType1LabelSubobject other = (EROType1LabelSubobject) obj;
+       if (this.label != other.label)
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("label", this.label);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROUnnumberedInterfaceSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROUnnumberedInterfaceSubobject.java
new file mode 100644 (file)
index 0000000..516a4c2
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of unnumbered Iterface Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3477">Section 4: Signalling
+ *      Unnumbered Links in EROs</a>
+ */
+public class EROUnnumberedInterfaceSubobject extends ExplicitRouteSubobject {
+       private final UnnumberedInterfaceIdentifier interfaceID;
+       private final IPv4Address routerID;
+
+       /**
+        * Constructs new Unnumbered Interface Subobject.
+        *
+        * @param routerID
+        *            IPv4Address
+        * @param interfaceID
+        *            UnnumberedInterfaceIdentifier
+        * @param loose
+        *            boolean
+        */
+       public EROUnnumberedInterfaceSubobject(final IPv4Address routerID, final UnnumberedInterfaceIdentifier interfaceID, boolean loose) {
+               super(loose);
+               this.routerID = routerID;
+               this.interfaceID = interfaceID;
+       }
+
+       /**
+        * Gets {@link IPv4Address} representation of router ID.
+        *
+        * @return IPv4Address
+        */
+       public IPv4Address getRouterID() {
+               return this.routerID;
+       }
+
+       /**
+        * Gets {@link UnnumberedInterfaceIdentifier} representation of Interface
+        * ID.
+        *
+        * @return UnnumberedInterfaceIdentifier
+        */
+       public UnnumberedInterfaceIdentifier getInterfaceID() {
+               return this.interfaceID;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.interfaceID == null) ? 0 : this.interfaceID.hashCode());
+               result = prime * result + ((this.routerID == null) ? 0 : this.routerID.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final EROUnnumberedInterfaceSubobject other = (EROUnnumberedInterfaceSubobject) obj;
+               if (this.interfaceID == null) {
+                       if (other.interfaceID != null)
+                               return false;
+               } else if (!this.interfaceID.equals(other.interfaceID))
+                       return false;
+               if (this.routerID == null) {
+                       if (other.routerID != null)
+                               return false;
+               } else if (!this.routerID.equals(other.routerID))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("EROUnnumberedInterfaceSubobject [interfaceID=");
+               builder.append(this.interfaceID);
+               builder.append(", routerID=");
+               builder.append(this.routerID);
+               builder.append(", loose=");
+               builder.append(this.loose);
+               builder.append("]");
+               return builder.toString();
+       }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("interfaceID", this.interfaceID);
+               toStringHelper.add("routerID", this.routerID);
+               toStringHelper.add("loose", this.loose);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROWavebandSwitchingLabelSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/EROWavebandSwitchingLabelSubobject.java
new file mode 100644 (file)
index 0000000..0ca4fc4
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Generalized Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3473#section-2.4">2.4. Waveband
+ *      Switching Object </a>
+ */
+public class EROWavebandSwitchingLabelSubobject extends EROLabelSubobject {
+
+    private final long wavebandId;
+
+    private final long startLabel;
+
+    private final long endLabel;
+
+    public EROWavebandSwitchingLabelSubobject(long wavebandId, long startLabel, long endLabel, boolean upStream, boolean loose) {
+       super(upStream);
+       this.wavebandId = wavebandId;
+       this.startLabel = startLabel;
+       this.endLabel = endLabel;
+    }
+
+    public long getWavebandId() {
+       return this.wavebandId;
+    }
+
+    public long getStartLabel() {
+       return this.startLabel;
+    }
+
+    public long getEndLabel() {
+       return this.endLabel;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (int) (this.endLabel ^ (this.endLabel >>> 32));
+       result = prime * result + (int) (this.startLabel ^ (this.startLabel >>> 32));
+       result = prime * result + (int) (this.wavebandId ^ (this.wavebandId >>> 32));
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final EROWavebandSwitchingLabelSubobject other = (EROWavebandSwitchingLabelSubobject) obj;
+       if (this.endLabel != other.endLabel)
+           return false;
+       if (this.startLabel != other.startLabel)
+           return false;
+       if (this.wavebandId != other.wavebandId)
+           return false;
+       return true;
+    }
+
+    @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("wavebandId", this.wavebandId);
+               toStringHelper.add("startLabel", this.startLabel);
+               toStringHelper.add("endLabel", this.endLabel);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/ExcludeRouteSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/ExcludeRouteSubobject.java
new file mode 100644 (file)
index 0000000..644115c
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.subobject;
+
+public abstract class ExcludeRouteSubobject {
+
+       protected final boolean mandatory;
+
+       public ExcludeRouteSubobject(boolean mandatory) {
+               this.mandatory = mandatory;
+       }
+
+       public boolean isMandatory() {
+               return this.mandatory;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (this.mandatory ? 1231 : 1237);
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final ExcludeRouteSubobject other = (ExcludeRouteSubobject) obj;
+               if (this.mandatory != other.mandatory)
+                       return false;
+               return true;
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/ExplicitRouteSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/ExplicitRouteSubobject.java
new file mode 100644 (file)
index 0000000..4ac1cef
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.subobject;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Base class for Explicit route subobjects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.3">4.3. Explicit
+ *      Route Object</a>
+ */
+public abstract class ExplicitRouteSubobject {
+    protected final boolean loose;
+
+    protected ExplicitRouteSubobject() {
+       this.loose = false;
+    }
+
+    protected ExplicitRouteSubobject(boolean loose) {
+       this.loose = loose;
+    }
+
+    /**
+     * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.3.3.1">Strict
+     *      and Loose Subobjects</a>
+     *
+     * @return true if L flag is set and false if is not.
+     */
+    public boolean isLoose() {
+       return this.loose;
+    }
+
+       @Override
+       public String toString(){
+               return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("loose", this.loose);
+               return toStringHelper;
+       }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + (this.loose ? 1231 : 1237);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final ExplicitRouteSubobject other = (ExplicitRouteSubobject) obj;
+       if (this.loose != other.loose)
+           return false;
+       return true;
+    }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROAsNumberSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROAsNumberSubobject.java
new file mode 100644 (file)
index 0000000..e9c9f61
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * Structure of Autonomous System Number Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.3.3.4">Section
+ *      4.3.3.4.: Subobject 32: Autonomous System Number</a>
+ */
+public class RROAsNumberSubobject extends ReportedRouteSubobject {
+
+    private final ASNumber asnumber;
+
+    /**
+     * Constructs new ASNumber Subobject.
+     *
+     * @param asnumber
+     *            ASNumber
+     */
+    public RROAsNumberSubobject(ASNumber asnumber) {
+       super();
+       this.asnumber = asnumber;
+    }
+
+    /**
+     * Gets {@link ASNumber}.
+     *
+     * @return ASNumber
+     */
+    public ASNumber getASNumber() {
+       return this.asnumber;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + ((this.asnumber == null) ? 0 : this.asnumber.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROAsNumberSubobject other = (RROAsNumberSubobject) obj;
+       if (this.asnumber == null) {
+           if (other.asnumber != null)
+               return false;
+       } else if (!this.asnumber.equals(other.asnumber))
+           return false;
+       return true;
+    }
+
+    @Override
+    public String toString() {
+       final StringBuilder builder = new StringBuilder();
+       builder.append("RROAsNumberSubobject [asnumber=");
+       builder.append(this.asnumber);
+       builder.append("]");
+       return builder.toString();
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROAttributesSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROAttributesSubobject.java
new file mode 100644 (file)
index 0000000..5020094
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.subobject;
+
+import java.util.Arrays;
+
+public class RROAttributesSubobject extends ReportedRouteSubobject {
+
+    private final byte[] attributes;
+
+    public RROAttributesSubobject(byte[] attributes) {
+       super();
+
+       if (attributes.length % 4 != 0)
+           throw new IllegalArgumentException("Attributes have to be multiple of 4.");
+
+       this.attributes = attributes;
+    }
+
+    public byte[] getAttributes() {
+       return this.attributes;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + Arrays.hashCode(this.attributes);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROAttributesSubobject other = (RROAttributesSubobject) obj;
+       if (!Arrays.equals(this.attributes, other.attributes))
+           return false;
+       return true;
+    }
+
+    @Override
+    public String toString() {
+       final StringBuilder builder = new StringBuilder();
+       builder.append("RROAttributesSubobject [attributes=");
+       builder.append(Arrays.toString(this.attributes));
+       builder.append("]");
+       return builder.toString();
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROGeneralizedLabelSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROGeneralizedLabelSubobject.java
new file mode 100644 (file)
index 0000000..a7ad497
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Generalized Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3471#section-3.2">3.2.
+ *      Generalized Label</a>
+ */
+public class RROGeneralizedLabelSubobject extends RROLabelSubobject {
+
+    private final byte[] label;
+
+    public RROGeneralizedLabelSubobject(byte[] label, boolean upStream) {
+       super(upStream);
+
+       if (label.length % 4 != 0)
+           throw new IllegalArgumentException("Length of label is not multiple of 4.");
+
+       this.label = label;
+    }
+
+    public byte[] getLabel() {
+       return this.label;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + Arrays.hashCode(this.label);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROGeneralizedLabelSubobject other = (RROGeneralizedLabelSubobject) obj;
+       if (!Arrays.equals(this.label, other.label))
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("label", this.label);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROIPAddressSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROIPAddressSubobject.java
new file mode 100644 (file)
index 0000000..77bd189
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ * Parametrized structure of RRO IP Address Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.4.1.1">Section
+ *      4.4.1.1: Subobject 1: IPv4 address</a> and <a
+ *      href="http://tools.ietf.org/html/rfc3209#section-4.4.1.2">Section
+ *      4.4.1.2: Subobject 2: IPv6 address</a>
+ *
+ * @param <T>
+ *            subtype of Prefix
+ */
+public class RROIPAddressSubobject<T extends Prefix<?>> extends ReportedRouteSubobject {
+
+    private final T prefix;
+
+    /**
+     * Local protection available
+     */
+    private final boolean localProtectionAvailable;
+
+    /**
+     * Local protection in use
+     */
+    private final boolean localProtectionInUse;
+
+    /**
+     * Constructs IPPrefix Subobject.
+     *
+     * @param prefix
+     *            T
+     * @param localProtectionAvailable
+     *            boolean
+     * @param localProtectionInUse
+     *            boolean
+     */
+    public RROIPAddressSubobject(T prefix, boolean localProtectionAvailable, boolean localProtectionInUse) {
+       super();
+       this.prefix = prefix;
+       this.localProtectionAvailable = localProtectionAvailable;
+       this.localProtectionInUse = localProtectionInUse;
+    }
+
+    /**
+     * Gets specific {@link Prefix}.
+     *
+     * @return prefix T
+     */
+    public T getPrefix() {
+       return this.prefix;
+    }
+
+    /**
+     * Returns tru if local protection is available.
+     *
+     * @return boolean
+     */
+    public boolean isLocalProtectionAvailable() {
+       return this.localProtectionAvailable;
+    }
+
+    /**
+     * Returns true if local protection is in use
+     *
+     * @return boolean
+     */
+    public boolean isLocalProtectionInUse() {
+       return this.localProtectionInUse;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + (this.localProtectionAvailable ? 1231 : 1237);
+       result = prime * result + (this.localProtectionInUse ? 1231 : 1237);
+       result = prime * result + ((this.prefix == null) ? 0 : this.prefix.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROIPAddressSubobject<?> other = (RROIPAddressSubobject<?>) obj;
+       if (this.localProtectionAvailable != other.localProtectionAvailable)
+           return false;
+       if (this.localProtectionInUse != other.localProtectionInUse)
+           return false;
+       if (this.prefix == null) {
+           if (other.prefix != null)
+               return false;
+       } else if (!this.prefix.equals(other.prefix))
+           return false;
+       return true;
+    }
+
+    @Override
+    public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("RROIPAddressSubobject [prefix=");
+               builder.append(this.prefix);
+               builder.append(", lpa=");
+               builder.append(this.localProtectionAvailable);
+               builder.append(", lpiu=");
+               builder.append(this.localProtectionInUse);
+               builder.append("]");
+               return builder.toString();
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROLabelSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROLabelSubobject.java
new file mode 100644 (file)
index 0000000..781faf7
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Label subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3473#section-5.1">Label ERO
+ *      subobject</a>
+ */
+public abstract class RROLabelSubobject extends ReportedRouteSubobject {
+
+    private final boolean upStream;
+
+    /**
+     * Constructs new Label subobject.
+     *
+     * @param upStream
+     *            if set label is upstream
+     * @param label
+     *            Label
+     * @param loose
+     *            boolean
+     */
+    public RROLabelSubobject(boolean upStream) {
+       this.upStream = upStream;
+    }
+
+    public boolean isUpStream() {
+       return this.upStream;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (this.upStream ? 1231 : 1237);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROLabelSubobject other = (RROLabelSubobject) obj;
+       if (this.upStream != other.upStream)
+           return false;
+       return true;
+    }
+
+    @Override
+       public String toString(){
+               return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("upStream", this.upStream);
+               return toStringHelper;
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROPathKeyWith128PCEIDSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROPathKeyWith128PCEIDSubobject.java
new file mode 100644 (file)
index 0000000..f9eed59
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import java.util.Arrays;
+
+public class RROPathKeyWith128PCEIDSubobject extends ReportedRouteSubobject {
+
+    private final int pathKey;
+
+    private final byte[] pceId;
+
+    public RROPathKeyWith128PCEIDSubobject(int pathKey, byte[] pceId) {
+       super();
+       this.pathKey = pathKey;
+       if (pceId == null)
+           throw new IllegalArgumentException("PCE ID can't be null.");
+
+       if (pceId.length != 16)
+           throw new IllegalArgumentException("PCE ID is not 16 bytes long.");
+
+       this.pceId = pceId;
+    }
+
+    public int getPathKey() {
+       return this.pathKey;
+    }
+
+    public byte[] getPceId() {
+       return this.pceId;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + this.pathKey;
+       result = prime * result + Arrays.hashCode(this.pceId);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROPathKeyWith128PCEIDSubobject other = (RROPathKeyWith128PCEIDSubobject) obj;
+       if (this.pathKey != other.pathKey)
+           return false;
+       if (!Arrays.equals(this.pceId, other.pceId))
+           return false;
+       return true;
+    }
+
+    @Override
+    public String toString() {
+       final StringBuilder builder = new StringBuilder();
+       builder.append("RROPathKeyWith128PCEIDSubobject [pathKey=");
+       builder.append(this.pathKey);
+       builder.append(", pceId=");
+       builder.append(Arrays.toString(this.pceId));
+       builder.append("]");
+       return builder.toString();
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROPathKeyWith32PCEIDSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROPathKeyWith32PCEIDSubobject.java
new file mode 100644 (file)
index 0000000..b78a3b2
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import java.util.Arrays;
+
+public class RROPathKeyWith32PCEIDSubobject extends ReportedRouteSubobject {
+
+    private final int pathKey;
+
+    private final byte[] pceId;
+
+    public RROPathKeyWith32PCEIDSubobject(int pathKey, byte[] pceId) {
+       super();
+       this.pathKey = pathKey;
+       if (pceId == null)
+           throw new IllegalArgumentException("PCE ID can't be null.");
+
+       if (pceId.length != 4)
+           throw new IllegalArgumentException("PCE ID is not 4 bytes long.");
+
+       this.pceId = pceId;
+    }
+
+    public int getPathKey() {
+       return this.pathKey;
+    }
+
+    public byte[] getPceId() {
+       return this.pceId;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + this.pathKey;
+       result = prime * result + Arrays.hashCode(this.pceId);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROPathKeyWith32PCEIDSubobject other = (RROPathKeyWith32PCEIDSubobject) obj;
+       if (this.pathKey != other.pathKey)
+           return false;
+       if (!Arrays.equals(this.pceId, other.pceId))
+           return false;
+       return true;
+    }
+
+    @Override
+    public String toString() {
+       final StringBuilder builder = new StringBuilder();
+       builder.append("RROPathKeyWith32PCEIDSubobject [pathKey=");
+       builder.append(this.pathKey);
+       builder.append(", pceId=");
+       builder.append(Arrays.toString(this.pceId));
+       builder.append("]");
+       return builder.toString();
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROProtectionSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROProtectionSubobject.java
new file mode 100644 (file)
index 0000000..0471d36
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+public abstract class RROProtectionSubobject extends ReportedRouteSubobject {
+    public RROProtectionSubobject() {
+       super();
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROProtectionType1Subobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROProtectionType1Subobject.java
new file mode 100644 (file)
index 0000000..67f98d0
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+
+public class RROProtectionType1Subobject extends RROProtectionSubobject {
+
+    private final boolean secondary;
+
+    private final byte linkFlags;
+
+    /**
+     * @param secondary
+     * @param linkFlags
+     */
+    public RROProtectionType1Subobject(boolean secondary, byte linkFlags) {
+       super();
+       this.secondary = secondary;
+       this.linkFlags = linkFlags;
+    }
+
+    /**
+     * @return the secondary
+     */
+    public boolean isSecondary() {
+       return this.secondary;
+    }
+
+    /**
+     * @return the linkFlags
+     */
+    public byte getLinkFlags() {
+       return this.linkFlags;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + this.linkFlags;
+       result = prime * result + (this.secondary ? 1231 : 1237);
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROProtectionType1Subobject other = (RROProtectionType1Subobject) obj;
+       if (this.linkFlags != other.linkFlags)
+           return false;
+       if (this.secondary != other.secondary)
+           return false;
+       return true;
+    }
+
+    @Override
+    public String toString() {
+       final StringBuilder builder = new StringBuilder();
+       builder.append("ProtectionType1Subobject [secondary=");
+       builder.append(this.secondary);
+       builder.append(", linkFlags=");
+       builder.append(this.linkFlags);
+       builder.append("]");
+       return builder.toString();
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROProtectionType2Subobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROProtectionType2Subobject.java
new file mode 100644 (file)
index 0000000..d617f4c
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+public class RROProtectionType2Subobject extends RROProtectionSubobject {
+    private final boolean secondaryLsp;
+
+    private final boolean protectionLsp;
+
+    private final boolean notification;
+
+    private final boolean operational;
+
+    private final byte lspFlags;
+
+    private final byte linkFlags;
+
+    private final boolean inPlace;
+
+    private final boolean required;
+
+    private final byte segFlags;
+
+    /**
+     * @param secondaryLsp
+     * @param protectionLsp
+     * @param notification
+     * @param operational
+     * @param lspFlags
+     * @param linkFlags
+     * @param inPlace
+     * @param required
+     * @param segFlags
+     */
+    public RROProtectionType2Subobject(boolean secondaryLsp, boolean protectionLsp, boolean notification, boolean operational, byte lspFlags, byte linkFlags,
+           boolean inPlace, boolean required, byte segFlags) {
+       super();
+       this.secondaryLsp = secondaryLsp;
+       this.protectionLsp = protectionLsp;
+       this.notification = notification;
+       this.operational = operational;
+       this.lspFlags = lspFlags;
+       this.linkFlags = linkFlags;
+       this.inPlace = inPlace;
+       this.required = required;
+       this.segFlags = segFlags;
+    }
+
+    /**
+     * @return the secondaryLsp
+     */
+    public boolean isSecondaryLsp() {
+       return this.secondaryLsp;
+    }
+
+    /**
+     * @return the protectionLsp
+     */
+    public boolean isProtectionLsp() {
+       return this.protectionLsp;
+    }
+
+    /**
+     * @return the notification
+     */
+    public boolean isNotification() {
+       return this.notification;
+    }
+
+    /**
+     * @return the operational
+     */
+    public boolean isOperational() {
+       return this.operational;
+    }
+
+    /**
+     * @return the lspFlags
+     */
+    public byte getLspFlags() {
+       return this.lspFlags;
+    }
+
+    /**
+     * @return the linkFlags
+     */
+    public byte getLinkFlags() {
+       return this.linkFlags;
+    }
+
+    /**
+     * @return the inPlace
+     */
+    public boolean isInPlace() {
+       return this.inPlace;
+    }
+
+    /**
+     * @return the required
+     */
+    public boolean isRequired() {
+       return this.required;
+    }
+
+    /**
+     * @return the segFlags
+     */
+    public byte getSegFlags() {
+       return this.segFlags;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + (this.inPlace ? 1231 : 1237);
+       result = prime * result + this.linkFlags;
+       result = prime * result + this.lspFlags;
+       result = prime * result + (this.notification ? 1231 : 1237);
+       result = prime * result + (this.operational ? 1231 : 1237);
+       result = prime * result + (this.protectionLsp ? 1231 : 1237);
+       result = prime * result + (this.required ? 1231 : 1237);
+       result = prime * result + (this.secondaryLsp ? 1231 : 1237);
+       result = prime * result + this.segFlags;
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROProtectionType2Subobject other = (RROProtectionType2Subobject) obj;
+       if (this.inPlace != other.inPlace)
+           return false;
+       if (this.linkFlags != other.linkFlags)
+           return false;
+       if (this.lspFlags != other.lspFlags)
+           return false;
+       if (this.notification != other.notification)
+           return false;
+       if (this.operational != other.operational)
+           return false;
+       if (this.protectionLsp != other.protectionLsp)
+           return false;
+       if (this.required != other.required)
+           return false;
+       if (this.secondaryLsp != other.secondaryLsp)
+           return false;
+       if (this.segFlags != other.segFlags)
+           return false;
+       return true;
+    }
+
+    @Override
+    public String toString() {
+       final StringBuilder builder = new StringBuilder();
+       builder.append("ProtectionType1Subobject [secondaryLsp=");
+       builder.append(this.secondaryLsp);
+       builder.append(", protectionLsp=");
+       builder.append(this.protectionLsp);
+       builder.append(", notification=");
+       builder.append(this.notification);
+       builder.append(", operational=");
+       builder.append(this.operational);
+       builder.append(", lspFlags=");
+       builder.append(this.lspFlags);
+       builder.append(", linkFlags=");
+       builder.append(this.linkFlags);
+       builder.append(", inPlace=");
+       builder.append(this.inPlace);
+       builder.append(", required=");
+       builder.append(this.required);
+       builder.append(", segFlags=");
+       builder.append(this.segFlags);
+       builder.append("]");
+       return builder.toString();
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROType1LabelSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROType1LabelSubobject.java
new file mode 100644 (file)
index 0000000..60ea64b
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Type 1 Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.1">4.1. Label
+ *      Object</a>
+ */
+public class RROType1LabelSubobject extends RROLabelSubobject {
+
+    private final long label;
+
+    public RROType1LabelSubobject(long label, boolean upStream) {
+       super(upStream);
+       this.label = label;
+    }
+
+    public long getLabel() {
+       return this.label;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (int) (this.label ^ (this.label >>> 32));
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROType1LabelSubobject other = (RROType1LabelSubobject) obj;
+       if (this.label != other.label)
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("label", this.label);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROUnnumberedInterfaceSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROUnnumberedInterfaceSubobject.java
new file mode 100644 (file)
index 0000000..9a96848
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+
+/**
+ * Structure of unnumbered Iterface Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3477">Section 4: Signalling
+ *      Unnumbered Links in EROs</a>
+ */
+public class RROUnnumberedInterfaceSubobject extends ReportedRouteSubobject {
+    private final UnnumberedInterfaceIdentifier interfaceID;
+    private final IPv4Address routerID;
+
+    /**
+     * Constructs new Unnumbered Interface Subobject.
+     *
+     * @param routerID
+     *            IPv4Address
+     * @param interfaceID
+     *            UnnumberedInterfaceIdentifier
+     */
+    public RROUnnumberedInterfaceSubobject(final IPv4Address routerID, final UnnumberedInterfaceIdentifier interfaceID) {
+       super();
+       this.routerID = routerID;
+       this.interfaceID = interfaceID;
+    }
+
+    /**
+     * Gets {@link IPv4Address} representation of router ID.
+     *
+     * @return IPv4Address
+     */
+    public IPv4Address getRouterID() {
+       return this.routerID;
+    }
+
+    /**
+     * Gets {@link UnnumberedInterfaceIdentifier} representation of Interface
+     * ID.
+     *
+     * @return UnnumberedInterfaceIdentifier
+     */
+    public UnnumberedInterfaceIdentifier getInterfaceID() {
+       return this.interfaceID;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + ((this.interfaceID == null) ? 0 : this.interfaceID.hashCode());
+       result = prime * result + ((this.routerID == null) ? 0 : this.routerID.hashCode());
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROUnnumberedInterfaceSubobject other = (RROUnnumberedInterfaceSubobject) obj;
+       if (this.interfaceID == null) {
+           if (other.interfaceID != null)
+               return false;
+       } else if (!this.interfaceID.equals(other.interfaceID))
+           return false;
+       if (this.routerID == null) {
+           if (other.routerID != null)
+               return false;
+       } else if (!this.routerID.equals(other.routerID))
+           return false;
+       return true;
+    }
+
+    @Override
+    public String toString() {
+       final StringBuilder builder = new StringBuilder();
+       builder.append("RROUnnumberedInterfaceSubobject [interfaceID=");
+       builder.append(this.interfaceID);
+       builder.append(", routerID=");
+       builder.append(this.routerID);
+       builder.append("]");
+       return builder.toString();
+    }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROWavebandSwitchingLabelSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/RROWavebandSwitchingLabelSubobject.java
new file mode 100644 (file)
index 0000000..b07ee8d
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Generalized Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3473#section-2.4">2.4. Waveband
+ *      Switching Object </a>
+ */
+public class RROWavebandSwitchingLabelSubobject extends RROLabelSubobject {
+
+    private final long wavebandId;
+
+    private final long startLabel;
+
+    private final long endLabel;
+
+    public RROWavebandSwitchingLabelSubobject(long wavebandId, long startLabel, long endLabel, boolean upStream) {
+       super(upStream);
+       this.wavebandId = wavebandId;
+       this.startLabel = startLabel;
+       this.endLabel = endLabel;
+    }
+
+    public long getWavebandId() {
+       return this.wavebandId;
+    }
+
+    public long getStartLabel() {
+       return this.startLabel;
+    }
+
+    public long getEndLabel() {
+       return this.endLabel;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = super.hashCode();
+       result = prime * result + (int) (this.endLabel ^ (this.endLabel >>> 32));
+       result = prime * result + (int) (this.startLabel ^ (this.startLabel >>> 32));
+       result = prime * result + (int) (this.wavebandId ^ (this.wavebandId >>> 32));
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (!super.equals(obj))
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final RROWavebandSwitchingLabelSubobject other = (RROWavebandSwitchingLabelSubobject) obj;
+       if (this.endLabel != other.endLabel)
+           return false;
+       if (this.startLabel != other.startLabel)
+           return false;
+       if (this.wavebandId != other.wavebandId)
+           return false;
+       return true;
+    }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("wavebandId", this.wavebandId);
+               toStringHelper.add("startLabel", this.startLabel);
+               toStringHelper.add("endLabel", this.endLabel);
+               return super.addToStringAttributes(toStringHelper);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/ReportedRouteSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/ReportedRouteSubobject.java
new file mode 100644 (file)
index 0000000..f2294db
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.subobject;
+
+public abstract class ReportedRouteSubobject {
+    protected ReportedRouteSubobject() {
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       return true;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       return prime;
+    }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROAsNumberSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROAsNumberSubobject.java
new file mode 100644 (file)
index 0000000..a9b282a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * Structure of Autonomous System Number Subobject. Defined in RFC5521.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1">Exclude Route
+ *      Object definition</a>
+ */
+public class XROAsNumberSubobject extends ExcludeRouteSubobject {
+
+       private final ASNumber asnumber;
+
+       /**
+        * Constructs new ASNumber Subobject.
+        *
+        * @param asnumber
+        *            ASNumber
+        * @param mandatory
+        *            boolean
+        */
+       public XROAsNumberSubobject(ASNumber asnumber, boolean mandatory) {
+               super(mandatory);
+               this.asnumber = asnumber;
+       }
+
+       /**
+        * Gets {@link ASNumber}.
+        *
+        * @return ASNumber
+        */
+       public ASNumber getASNumber() {
+               return this.asnumber;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.asnumber == null) ? 0 : this.asnumber.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final XROAsNumberSubobject other = (XROAsNumberSubobject) obj;
+               if (this.asnumber == null) {
+                       if (other.asnumber != null)
+                               return false;
+               } else if (!this.asnumber.equals(other.asnumber))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("XROAsNumberSubobject [asnumber=");
+               builder.append(this.asnumber);
+               builder.append(", mandatory=");
+               builder.append(this.mandatory);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROIPPrefixSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROIPPrefixSubobject.java
new file mode 100644 (file)
index 0000000..b9e593e
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ * Parametrized structure of IP Prefix Subobject. Defined in RFC5521.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1">Exclude Route
+ *      Object definition</a>
+ *
+ * @param <T>
+ *            subtype of Prefix
+ */
+public class XROIPPrefixSubobject<T extends Prefix<?>> extends ExcludeRouteSubobject {
+
+       private final XROSubobjectAttribute attribute;
+
+       private final T prefix;
+
+       /**
+        * Constructs IPPrefix Subobject.
+        *
+        * @param prefix
+        *            T
+        * @param mandatory
+        *            boolean
+        * @param attribute
+        *            XROSubobjectAttribute
+        */
+       public XROIPPrefixSubobject(T prefix, boolean mandatory, XROSubobjectAttribute attribute) {
+               super(mandatory);
+               this.attribute = attribute;
+               this.prefix = prefix;
+       }
+
+       /**
+        * Gets specific {@link Prefix}.
+        *
+        * @return prefix T
+        */
+       public T getPrefix() {
+               return this.prefix;
+       }
+
+       /**
+        * Gets the attribute of the subobject
+        *
+        * @return the attribute
+        */
+       public XROSubobjectAttribute getAttribute() {
+               return this.attribute;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.attribute == null) ? 0 : this.attribute.hashCode());
+               result = prime * result + ((this.prefix == null) ? 0 : this.prefix.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final XROIPPrefixSubobject<?> other = (XROIPPrefixSubobject<?>) obj;
+               if (this.attribute != other.attribute)
+                       return false;
+               if (this.prefix == null) {
+                       if (other.prefix != null)
+                               return false;
+               } else if (!this.prefix.equals(other.prefix))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("XROIPPrefixSubobject [attribute=");
+               builder.append(this.attribute);
+               builder.append(", prefix=");
+               builder.append(this.prefix);
+               builder.append(", mandatory=");
+               builder.append(this.mandatory);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROSRLGSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROSRLGSubobject.java
new file mode 100644 (file)
index 0000000..803b699
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+
+/**
+ * Structure of Shared Risk Link Group Subobject. Defined in RFC5521.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1">Exclude Route
+ *      Object definition</a>
+ */
+public class XROSRLGSubobject extends ExcludeRouteSubobject {
+
+       private final XROSubobjectAttribute attribute;
+
+       private final SharedRiskLinkGroup srlgId;
+
+       /**
+        * Constructs new Shared Risk Link Group Subobject.
+        *
+        * @param srlgId
+        *            SharedRiskLinkGroup
+        * @param mandatory
+        *            boolean
+        */
+       public XROSRLGSubobject(SharedRiskLinkGroup srlgId, boolean mandatory) {
+               super(mandatory);
+               this.attribute = XROSubobjectAttribute.SRLG;
+               this.srlgId = srlgId;
+       }
+
+       /**
+        * Gets the Shared Risk Link Group.
+        *
+        * @return SharedRiskLinkGroup
+        */
+       public SharedRiskLinkGroup getSrlgId() {
+               return this.srlgId;
+       }
+
+       /**
+        * Gets the attribute of the subobject
+        *
+        * @return the attribute
+        */
+       public XROSubobjectAttribute getAttribute() {
+               return this.attribute;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("XROSRLGSubobject [attribute=");
+               builder.append(this.attribute);
+               builder.append(", srlgId=");
+               builder.append(this.srlgId.getValue());
+               builder.append(", mandatory=");
+               builder.append(this.mandatory);
+               builder.append("]");
+               return builder.toString();
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.attribute == null) ? 0 : this.attribute.hashCode());
+               result = prime * result + ((this.srlgId == null) ? 0 : this.srlgId.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final XROSRLGSubobject other = (XROSRLGSubobject) obj;
+               if (this.attribute != other.attribute)
+                       return false;
+               if (this.srlgId == null) {
+                       if (other.srlgId != null)
+                               return false;
+               } else if (!this.srlgId.equals(other.srlgId))
+                       return false;
+               return true;
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROSubobjectAttribute.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROSubobjectAttribute.java
new file mode 100644 (file)
index 0000000..259227c
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.subobject;
+
+/**
+ * Enumerable for attributes of subobjects. Defined in 5521.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1">Exclude Route
+ *      Object definition</a>
+ */
+public enum XROSubobjectAttribute {
+       /**
+        * The subobject is to be interpreted as an interface or set of interfaces.
+        */
+       INTERFACE,
+       /**
+        * The subobject is to be interpreted as a node or set of nodes.
+        */
+       NODE,
+       /**
+        * The subobject identifies an SRLG explicitly or indicates all of the SRLGs
+        * associated with the resource or resources identified by the subobject.
+        */
+       SRLG;
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROUnnumberedInterfaceSubobject.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/subobject/XROUnnumberedInterfaceSubobject.java
new file mode 100644 (file)
index 0000000..a05887a
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+
+/**
+ * Structure of unnumbered Iterface Subobject. Defined in RFC5521.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1">Exclude Route
+ *      Object definition</a>
+ */
+public class XROUnnumberedInterfaceSubobject extends ExcludeRouteSubobject {
+
+       private final XROSubobjectAttribute attribute;
+
+       private final UnnumberedInterfaceIdentifier interfaceID;
+
+       private final IPv4Address routerID;
+
+       /**
+        * Constructs new Unnumbered Interface Subobject.
+        *
+        * @param routerID
+        *            IPv4Address
+        * @param interfaceID
+        *            UnnumberedInterfaceIdentifier
+        * @param mandatory
+        *            boolean
+        * @param attribute
+        *            XROSubobjectAttribute
+        */
+       public XROUnnumberedInterfaceSubobject(final IPv4Address routerID, final UnnumberedInterfaceIdentifier interfaceID, boolean mandatory,
+                       XROSubobjectAttribute attribute) {
+               super(mandatory);
+               this.attribute = attribute;
+               this.routerID = routerID;
+               this.interfaceID = interfaceID;
+       }
+
+       /**
+        * Gets the attribute of the subobject
+        *
+        * @return the attribute
+        */
+       public XROSubobjectAttribute getAttribute() {
+               return this.attribute;
+       }
+
+       /**
+        * Gets {@link IPv4Address} representation of router ID.
+        *
+        * @return IPv4Address
+        */
+       public IPv4Address getRouterID() {
+               return this.routerID;
+       }
+
+       /**
+        * Gets {@link UnnumberedInterfaceIdentifier} representation of Interface
+        * ID.
+        *
+        * @return UnnumberedInterfaceIdentifier
+        */
+       public UnnumberedInterfaceIdentifier getInterfaceID() {
+               return this.interfaceID;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = super.hashCode();
+               result = prime * result + ((this.attribute == null) ? 0 : this.attribute.hashCode());
+               result = prime * result + ((this.interfaceID == null) ? 0 : this.interfaceID.hashCode());
+               result = prime * result + ((this.routerID == null) ? 0 : this.routerID.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!super.equals(obj))
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final XROUnnumberedInterfaceSubobject other = (XROUnnumberedInterfaceSubobject) obj;
+               if (this.attribute != other.attribute)
+                       return false;
+               if (this.interfaceID == null) {
+                       if (other.interfaceID != null)
+                               return false;
+               } else if (!this.interfaceID.equals(other.interfaceID))
+                       return false;
+               if (this.routerID == null) {
+                       if (other.routerID != null)
+                               return false;
+               } else if (!this.routerID.equals(other.routerID))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("XROUnnumberedInterfaceSubobject [attribute=");
+               builder.append(this.attribute);
+               builder.append(", interfaceID=");
+               builder.append(this.interfaceID);
+               builder.append(", routerID=");
+               builder.append(this.routerID);
+               builder.append(", mandatory=");
+               builder.append(this.mandatory);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/AbstractLSPIdentifiersTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/AbstractLSPIdentifiersTlv.java
new file mode 100644 (file)
index 0000000..3f1dee3
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.pcep.concepts.ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+
+/**
+ * Basic structure of LSP Identifiers TLV.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ *      Identifiers TLVs</a>
+ * @param <T>
+ */
+public abstract class AbstractLSPIdentifiersTlv<T extends NetworkAddress<T>> implements LSPIdentifiersTlv<T> {
+       private static final long serialVersionUID = 2386922658825295806L;
+
+       private final T senderAddress;
+
+       private final LSPIdentifier lspID;
+
+       private final TunnelIdentifier tunnelID;
+
+       private final ExtendedTunnelIdentifier<T> extendedTunnelID;
+
+       /**
+        * Construct LSP Identifier TLV with mandatory objects.
+        *
+        * @param senderAddress
+        * @param lspID
+        * @param tunnelID
+        * @param extendedTunnelID
+        */
+       protected AbstractLSPIdentifiersTlv(T senderAddress, LSPIdentifier lspID, TunnelIdentifier tunnelID, ExtendedTunnelIdentifier<T> extendedTunnelID) {
+               if (senderAddress == null)
+                       throw new IllegalArgumentException("SenderAdress is mandatory.");
+               this.senderAddress = senderAddress;
+
+               if (lspID == null)
+                       throw new IllegalArgumentException("LspID is mandatory.");
+               this.lspID = lspID;
+
+               if (tunnelID == null)
+                       throw new IllegalArgumentException("TunnelID is mandatory.");
+               this.tunnelID = tunnelID;
+
+               if (extendedTunnelID == null)
+                       throw new IllegalArgumentException("ExtendedTunnelID is mandatory.");
+               this.extendedTunnelID = extendedTunnelID;
+       }
+
+       @Override
+       public T getSenderAddress() {
+               return this.senderAddress;
+       }
+
+       @Override
+       public LSPIdentifier getLspID() {
+               return this.lspID;
+       }
+
+       @Override
+       public TunnelIdentifier getTunnelID() {
+               return this.tunnelID;
+       }
+
+       @Override
+       public ExtendedTunnelIdentifier<T> getExtendedTunnelID() {
+               return this.extendedTunnelID;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.extendedTunnelID == null) ? 0 : this.extendedTunnelID.hashCode());
+               result = prime * result + ((this.lspID == null) ? 0 : this.lspID.hashCode());
+               result = prime * result + ((this.senderAddress == null) ? 0 : this.senderAddress.hashCode());
+               result = prime * result + ((this.tunnelID == null) ? 0 : this.tunnelID.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final AbstractLSPIdentifiersTlv<?> other = (AbstractLSPIdentifiersTlv<?>) obj;
+               if (this.extendedTunnelID == null) {
+                       if (other.extendedTunnelID != null)
+                               return false;
+               } else if (!this.extendedTunnelID.equals(other.extendedTunnelID))
+                       return false;
+               if (this.lspID == null) {
+                       if (other.lspID != null)
+                               return false;
+               } else if (!this.lspID.equals(other.lspID))
+                       return false;
+               if (this.senderAddress == null) {
+                       if (other.senderAddress != null)
+                               return false;
+               } else if (!this.senderAddress.equals(other.senderAddress))
+                       return false;
+               if (this.tunnelID == null) {
+                       if (other.tunnelID != null)
+                               return false;
+               } else if (!this.tunnelID.equals(other.tunnelID))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("AbstractLSPIdentifiersTlv [senderAddress=");
+               builder.append(this.senderAddress);
+               builder.append(", lspID=");
+               builder.append(this.lspID);
+               builder.append(", tunnelID=");
+               builder.append(this.tunnelID);
+               builder.append(", extendedTunnelID=");
+               builder.append(this.extendedTunnelID);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/ByPassTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/ByPassTlv.java
new file mode 100644 (file)
index 0000000..65475d0
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ *     Structure of No Path Vector TLV.
+ *
+ *     @see <a href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-protection-00#section-4.3"
+ *                     Bypass Tlv</a>
+ */
+public class ByPassTlv implements PCEPTlv {
+
+       private static final long serialVersionUID = 5879892226322401651L;
+
+       private final boolean nodeProtection;
+
+       private final boolean localProtectionInUse;
+
+       private final IPv4Address bypassAddress;
+
+       /**
+        * Constructs ByPass Tlv.
+        *
+        * @param nodeProtection
+        *              boolean
+        * @param localProtectionInUse
+        *              boolean
+        * @param bypassAddress
+        *              IPv4Address
+        */
+       public ByPassTlv(final boolean nodeProtection, final boolean localProtectionInUse,
+                       final IPv4Address bypassAddress) {
+               this.nodeProtection = nodeProtection;
+               this.localProtectionInUse = localProtectionInUse;
+               this.bypassAddress = bypassAddress;
+       }
+
+       /**
+        * The N Flag indicates whether the Bypass is used for node-protection.
+        * If the N flag is set to 1, the Bypass is used for node-protection.
+        * If the N flag is 0, the Bypass is used for link-protection.
+        *
+        * @return the nodeProtection
+        */
+       public final boolean isNodeProtection() {
+               return this.nodeProtection;
+       }
+
+       /**
+        * The I Flag indicates that local repair mechanism is in use.
+        *
+        * @return the localProtectionInUse
+        */
+       public final boolean isLocalProtectionInUse() {
+               return this.localProtectionInUse;
+       }
+
+       /**
+        * For link protection, the Bypass IPv4 Address is
+     * the nexthop address of the protected link in the paths of the
+     * protected LSPs.  For node protection, the Bypass IPv4 Address is
+     * the node addresses of the protected node.
+     *
+        * @return the bypassAddress
+        */
+       public final IPv4Address getBypassAddress() {
+               return this.bypassAddress;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("ByPassTlv [nodeProtection=");
+               builder.append(this.nodeProtection);
+               builder.append(", localProtectionInUse=");
+               builder.append(this.localProtectionInUse);
+               builder.append(", bypassAddress=");
+               builder.append(this.bypassAddress);
+               builder.append("]");
+               return builder.toString();
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result
+                               + ((this.bypassAddress == null) ? 0 : this.bypassAddress.hashCode());
+               result = prime * result + (this.localProtectionInUse ? 1231 : 1237);
+               result = prime * result + (this.nodeProtection ? 1231 : 1237);
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof ByPassTlv))
+                       return false;
+               final ByPassTlv other = (ByPassTlv) obj;
+               if (this.bypassAddress == null) {
+                       if (other.bypassAddress != null)
+                               return false;
+               } else if (!this.bypassAddress.equals(other.bypassAddress))
+                       return false;
+               if (this.localProtectionInUse != other.localProtectionInUse)
+                       return false;
+               if (this.nodeProtection != other.nodeProtection)
+                       return false;
+               return true;
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/IPv4LSPIdentifiersTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/IPv4LSPIdentifiersTlv.java
new file mode 100644 (file)
index 0000000..8867473
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.concepts.ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+
+/**
+ * Specific structure for IPv4 LSP Identifier TLV.
+ * 
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ *      Identifiers TLVs</a>
+ */
+public final class IPv4LSPIdentifiersTlv extends AbstractLSPIdentifiersTlv<IPv4Address> {
+       private static final long serialVersionUID = -8249620306610957898L;
+
+       /**
+        * Constructs new IPv4 LSP Identifiers TLV.
+        * 
+        * @param senderAddress
+        *            {@link IPv4Address}
+        * @param lspID
+        *            {@link LSPIdentifier}
+        * @param tunnelID
+        *            {@link TunnelIdentifier}
+        * @param extendedTunnelID
+        *            {@link ExtendedTunnelIdentifier}
+        */
+       public IPv4LSPIdentifiersTlv(IPv4Address senderAddress, LSPIdentifier lspID, TunnelIdentifier tunnelID,
+                       ExtendedTunnelIdentifier<IPv4Address> extendedTunnelID) {
+               super(senderAddress, lspID, tunnelID, extendedTunnelID);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/IPv6LSPIdentifiersTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/IPv6LSPIdentifiersTlv.java
new file mode 100644 (file)
index 0000000..6fa94b6
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.concepts.ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+
+/**
+ * Specific structure of IPv6 LSP Identifier TLV.
+ * 
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ *      Identifiers TLVs</a>
+ */
+public final class IPv6LSPIdentifiersTlv extends AbstractLSPIdentifiersTlv<IPv6Address> {
+       private static final long serialVersionUID = 4188840025844510894L;
+
+       /**
+        * Constructs new IPv6 LSP Identifiers TLV.
+        * 
+        * @param senderAddress
+        *            {@link IPv6Address}
+        * @param lspID
+        *            {@link LSPIdentifier}
+        * @param tunnelID
+        *            {@link TunnelIdentifier}
+        * @param extendedTunnelID
+        *            {@link ExtendedTunnelIdentifier}
+        */
+       public IPv6LSPIdentifiersTlv(IPv6Address senderAddress, LSPIdentifier lspID, TunnelIdentifier tunnelID,
+                       ExtendedTunnelIdentifier<IPv6Address> extendedTunnelID) {
+               super(senderAddress, lspID, tunnelID, extendedTunnelID);
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPCleanupTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPCleanupTlv.java
new file mode 100644 (file)
index 0000000..c529949
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of LSP Cleanup Tlv
+ *
+ * @see <a href="http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt#section-6.2.1">LSP-CLEANUP TLV</a>
+ */
+public class LSPCleanupTlv implements PCEPTlv {
+
+       private static final long serialVersionUID = -2540695596612553355L;
+
+       private final int timeout;
+
+       /**
+        * Creates new LSP Cleanup Tlv.
+        *
+        */
+       public LSPCleanupTlv(int timeout) {
+               if (timeout < 0 || timeout > Integer.MAX_VALUE)
+                       throw new IllegalArgumentException("Timeout (" + timeout + ") cannot be negative or bigger than 2^31 -1.");
+               this.timeout = timeout;
+       }
+
+       /**
+        * @return the timeout
+        */
+       public final int getTimeout() {
+               return this.timeout;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + this.timeout;
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof LSPCleanupTlv))
+                       return false;
+               final LSPCleanupTlv other = (LSPCleanupTlv) obj;
+               if (this.timeout != other.timeout)
+                       return false;
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("LSPCleanupTlv [timeout=");
+               builder.append(this.timeout);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPIdentifiersTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPIdentifiersTlv.java
new file mode 100644 (file)
index 0000000..5247000
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+
+/**
+ * Interface defining basic LSPIdentifiersTLV.
+ * 
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ *      Identifiers TLVs</a>
+ * @param <T>
+ */
+public interface LSPIdentifiersTlv<T extends NetworkAddress<T>> extends PCEPTlv {
+
+       /**
+        * Gets specific senders {@link NetworkAddress}.
+        * 
+        * @return T sender network address
+        */
+       public T getSenderAddress();
+
+       /**
+        * Gets {@link LSPIdentifier}.
+        * 
+        * @return LSPIdentifier
+        */
+       public LSPIdentifier getLspID();
+
+       /**
+        * Gets {@link TunnelIdentifier}.
+        * 
+        * @return TunnelIdentifier
+        */
+       public TunnelIdentifier getTunnelID();
+
+       /**
+        * Gets specific {@link ExtendedTunnelIdentifier}.
+        * 
+        * 
+        * @return ExtendedTunnelIdentifier
+        */
+       public ExtendedTunnelIdentifier<T> getExtendedTunnelID();
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPStateDBVersionTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPStateDBVersionTlv.java
new file mode 100644 (file)
index 0000000..c8a0742
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of LSP State DB Version TLV.
+ * 
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.1.2">LSP
+ *      State Database Version TLV</a>
+ */
+public class LSPStateDBVersionTlv implements PCEPTlv {
+       private static final long serialVersionUID = 3165807743418210453L;
+       private final long dbVersion;
+
+       /**
+        * Construct new LSP State DB Version TLV.
+        * 
+        * @param dbVersion
+        *            long
+        */
+       public LSPStateDBVersionTlv(long dbVersion) {
+               this.dbVersion = dbVersion;
+       }
+
+       /**
+        * Gets long representation of DB Version.
+        * 
+        * @return long
+        */
+       public long getDbVersion() {
+               return this.dbVersion;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (int) (this.dbVersion ^ (this.dbVersion >>> 32));
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final LSPStateDBVersionTlv other = (LSPStateDBVersionTlv) obj;
+               if (this.dbVersion != other.dbVersion)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("LSPStateDBVersionTlv [dbVersion=");
+               builder.append(this.dbVersion);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPSymbolicNameTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPSymbolicNameTlv.java
new file mode 100644 (file)
index 0000000..87fb490
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+
+/**
+ * Structure of LSP Symbolic Name Tlv.
+ * 
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.1">The
+ *      LSP Symbolic Name TLV</a>
+ */
+public class LSPSymbolicNameTlv implements PCEPTlv {
+       private static final long serialVersionUID = 2525226814028262452L;
+       private final LSPSymbolicName symbolicName;
+
+       /**
+        * Constructs new LSP Symbolic Name TLV.
+        * 
+        * @param symbolicName
+        *            LSPSymbolicName
+        */
+       public LSPSymbolicNameTlv(LSPSymbolicName symbolicName) {
+               this.symbolicName = symbolicName;
+       }
+
+       /**
+        * Gets {@link LSPSymbolicName}.
+        * 
+        * @return LSPSymbolicName
+        */
+       public LSPSymbolicName getSymbolicName() {
+               return this.symbolicName;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.symbolicName == null) ? 0 : this.symbolicName.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final LSPSymbolicNameTlv other = (LSPSymbolicNameTlv) obj;
+               if (this.symbolicName == null) {
+                       if (other.symbolicName != null)
+                               return false;
+               } else if (!this.symbolicName.equals(other.symbolicName))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("LSPSymbolicNameTlv [symbolicName=");
+               builder.append(this.symbolicName);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPUpdateErrorTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/LSPUpdateErrorTlv.java
new file mode 100644 (file)
index 0000000..64a4ed7
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of LSP Update Error TLV.
+ * 
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.3">LSP
+ *      Update Error Code TLV</a>
+ */
+public class LSPUpdateErrorTlv implements PCEPTlv {
+       private static final long serialVersionUID = -6919035417806059716L;
+       private final byte[] errorCode;
+
+       /**
+        * Constructs new LSP Update Error Tlv.
+        * 
+        * @param errorCode
+        *            byte[]. Size has to be 4 bytes.
+        */
+       public LSPUpdateErrorTlv(byte[] errorCode) {
+               if (errorCode.length != 4)
+                       throw new IllegalArgumentException("Update error code has wrong size.");
+               this.errorCode = errorCode;
+       }
+
+       /**
+        * TBD
+        * 
+        * @return error code as byte[]
+        */
+       public byte[] getErrorCode() {
+               return this.errorCode;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + Arrays.hashCode(this.errorCode);
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final LSPUpdateErrorTlv other = (LSPUpdateErrorTlv) obj;
+               if (!Arrays.equals(this.errorCode, other.errorCode))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("LSPUpdateErrorTlv [errorCode=");
+               builder.append(Arrays.toString(this.errorCode));
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/NoPathVectorTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/NoPathVectorTlv.java
new file mode 100644 (file)
index 0000000..b9276e1
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of No Path Vector TLV. Extended to conform RFC5557.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.5">NO-PATH Object
+ *      [RFC5440]</a> - defined in text
+ * @see <a href="http://tools.ietf.org/html/rfc5557#section-5.7">NO-PATH
+ *      Indicator [RFC5557]</a>
+ */
+public class NoPathVectorTlv implements PCEPTlv {
+
+       private static final long serialVersionUID = -4993945476359800826L;
+
+       private final boolean pceUnavailable;
+
+       private final boolean unknownDest;
+
+       private final boolean unknownSrc;
+
+       private final boolean noGCOSolution;
+
+       private final boolean noGCOMigrationPath;
+
+       private final boolean reachablityProblem;
+
+       /**
+        * Constructs new No Path Vector Tlv.
+        * 
+        * @param pceUnavailable
+        *            boolean
+        * @param unknownDest
+        *            boolean
+        * @param unknownSrc
+        *            boolean
+        * @param noGCOSolution
+        *            boolean
+        * @param noGCOMigrationPath
+        *            boolean
+        */
+       public NoPathVectorTlv(boolean pceUnavailable, boolean unknownDest, boolean unknownSrc, boolean noGCOSolution, boolean noGCOMigrationPath,
+                       boolean reachabilityProblem) {
+               super();
+               this.pceUnavailable = pceUnavailable;
+               this.unknownDest = unknownDest;
+               this.unknownSrc = unknownSrc;
+               this.noGCOSolution = noGCOSolution;
+               this.noGCOMigrationPath = noGCOMigrationPath;
+               this.reachablityProblem = reachabilityProblem;
+       }
+
+       /**
+        * Returns true if PCE currently unavailable
+        * 
+        * @return boolean
+        */
+       public boolean isPceUnavailable() {
+               return this.pceUnavailable;
+       }
+
+       /**
+        * Returns true if unknown destination
+        * 
+        * @return boolean
+        */
+       public boolean isUnknownDest() {
+               return this.unknownDest;
+       }
+
+       /**
+        * Returns true if unknown source
+        * 
+        * @return boolean
+        */
+       public boolean isUnknownSrc() {
+               return this.unknownSrc;
+       }
+
+       /**
+        * If returns true the PCE indicates that no migration path was found.
+        * 
+        * @return boolean
+        */
+       public boolean isNoGCOSolution() {
+               return this.noGCOSolution;
+       }
+
+       /**
+        * If returns true the PCE indicates no feasible solution was found that
+        * meets all the constraints associated with global concurrent path
+        * optimization in the PCRep message
+        * 
+        * @return boolean
+        */
+       public boolean isNoGCOMigrationPath() {
+               return this.noGCOMigrationPath;
+       }
+
+       /**
+        * @return the reachablityProblem
+        */
+       public boolean isReachablityProblem() {
+               return this.reachablityProblem;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (this.noGCOMigrationPath ? 1231 : 1237);
+               result = prime * result + (this.noGCOSolution ? 1231 : 1237);
+               result = prime * result + (this.pceUnavailable ? 1231 : 1237);
+               result = prime * result + (this.reachablityProblem ? 1231 : 1237);
+               result = prime * result + (this.unknownDest ? 1231 : 1237);
+               result = prime * result + (this.unknownSrc ? 1231 : 1237);
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final NoPathVectorTlv other = (NoPathVectorTlv) obj;
+               if (this.noGCOMigrationPath != other.noGCOMigrationPath)
+                       return false;
+               if (this.noGCOSolution != other.noGCOSolution)
+                       return false;
+               if (this.pceUnavailable != other.pceUnavailable)
+                       return false;
+               if (this.reachablityProblem != other.reachablityProblem)
+                       return false;
+               if (this.unknownDest != other.unknownDest)
+                       return false;
+               if (this.unknownSrc != other.unknownSrc)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("NoPathVectorTlv [pceUnavailable=");
+               builder.append(this.pceUnavailable);
+               builder.append(", unknownDest=");
+               builder.append(this.unknownDest);
+               builder.append(", unknownSrc=");
+               builder.append(this.unknownSrc);
+               builder.append(", noGCOSolution=");
+               builder.append(this.noGCOSolution);
+               builder.append(", noGCOMigrationPath=");
+               builder.append(this.noGCOMigrationPath);
+               builder.append(", reachablityProblem=");
+               builder.append(this.reachablityProblem);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/NodeIdentifierTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/NodeIdentifierTlv.java
new file mode 100644 (file)
index 0000000..0f7849e
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.tlv;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of Node Identifier TLV.
+ *
+ * @see draft-ietf-pce-stateful-pce-01 (sec. 7.1.3) - NODE_IDENTIFIER_TLV
+ */
+public class NodeIdentifierTlv implements PCEPTlv {
+       private static final long serialVersionUID = -7959631526276210055L;
+       private final byte[] value;
+
+       /**
+        * Constructs new Node Identifier TLV.
+        *
+        * @param value
+        *            byte[]
+        */
+       public NodeIdentifierTlv(byte[] value) {
+               if (value == null)
+                       throw new IllegalArgumentException("Value is mandatory.");
+               if (value.length == 0)
+                       throw new IllegalArgumentException("Value has to be long at least 1 byte.");
+
+               this.value = value;
+       }
+
+       /**
+        * Gets value of Node Identifier TLV as Bytes Array.
+        *
+        * @return byte[]
+        */
+       public byte[] getValue() {
+               return this.value;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + Arrays.hashCode(this.value);
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final NodeIdentifierTlv other = (NodeIdentifierTlv) obj;
+               if (!Arrays.equals(this.value, other.value))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("NodeIdentifierTlv [value=");
+               try {
+                       builder.append(Charset.forName("UTF-8").newDecoder().decode(ByteBuffer.wrap(this.value)).toString());
+               } catch (final CharacterCodingException e) {
+                       builder.append(Arrays.toString(this.value));
+               }
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/OFListTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/OFListTlv.java
new file mode 100644 (file)
index 0000000..bedbe3c
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.tlv;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * It MAY be carried within an OPEN object sent by a PCE in an Open message to a
+ * PCEP peer so as to indicate the list of supported objective functions.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc5541#section-2.1">OF-List TLV</a>
+ */
+public class OFListTlv implements PCEPTlv {
+       private static final long serialVersionUID = 3409582385994162451L;
+
+       private final List<PCEPOFCodes> ofCodes;
+
+       /**
+        * Constructs new objective functions list tlv
+        * 
+        * @param ofCodes
+        *            lit of objective functions
+        */
+       public OFListTlv(List<PCEPOFCodes> ofCodes) {
+               super();
+               this.ofCodes = ofCodes;
+       }
+
+       /**
+        * Gets list of objective functions
+        * 
+        * @return list of objective functions
+        */
+       public List<PCEPOFCodes> getOfCodes() {
+               return this.ofCodes;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.ofCodes == null) ? 0 : this.ofCodes.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final OFListTlv other = (OFListTlv) obj;
+               if (this.ofCodes == null) {
+                       if (other.ofCodes != null)
+                               return false;
+               } else if (!this.ofCodes.equals(other.ofCodes))
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("OFListTlv [ofCodes=");
+               builder.append(this.ofCodes);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/OrderTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/OrderTlv.java
new file mode 100644 (file)
index 0000000..8d04b2d
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * The Order TLV is an optional TLV in the RP object, that indicates the order
+ * in which the old TE LSP must be removed and the new TE LSP must be setup
+ * during a reoptimization. It is carried in the PCRep message in response to a
+ * reoptimization request.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc5557#section-5.4">The Order
+ *      Response [RFC5557]</a>
+ */
+public class OrderTlv implements PCEPTlv {
+
+       private static final long serialVersionUID = 4275350142878198146L;
+
+       private final long deleteOrder;
+       private final long setupOrder;
+
+       /**
+        * Constructs new Order tlv with all mandatory objects.
+        * 
+        * @param deleteOrder
+        *            32-bit integer
+        * @param setupOrder
+        *            32-bit integer
+        */
+       public OrderTlv(long deleteOrder, long setupOrder) {
+               super();
+               this.deleteOrder = deleteOrder;
+               this.setupOrder = setupOrder;
+       }
+
+       /**
+        * Gets the delete order
+        * 
+        * @return the delete order
+        */
+       public long getDeleteOrder() {
+               return this.deleteOrder;
+       }
+
+       /**
+        * Gets the setup order
+        * 
+        * @return the setup order
+        */
+       public long getSetupOrder() {
+               return this.setupOrder;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("OrderTlv [deleteOrder=");
+               builder.append(this.deleteOrder);
+               builder.append(", setupOrder=");
+               builder.append(this.setupOrder);
+               builder.append("]");
+               return builder.toString();
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (int) (this.deleteOrder ^ (this.deleteOrder >>> 32));
+               result = prime * result + (int) (this.setupOrder ^ (this.setupOrder >>> 32));
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final OrderTlv other = (OrderTlv) obj;
+               if (this.deleteOrder != other.deleteOrder)
+                       return false;
+               if (this.setupOrder != other.setupOrder)
+                       return false;
+               return true;
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/OverloadedDurationTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/OverloadedDurationTlv.java
new file mode 100644 (file)
index 0000000..e1af086
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of Overloaded Duratioon Tlv.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.14">NOTIFICATION
+ *      Object</a> - defined in text
+ */
+public class OverloadedDurationTlv implements PCEPTlv {
+       private static final long serialVersionUID = -5829314427598008054L;
+       private final int value;
+
+       /**
+        * Construct new Overloaded Duration Tlv.
+        * 
+        * @param value
+        *            int
+        */
+       public OverloadedDurationTlv(int value) {
+               this.value = value;
+       }
+
+       /**
+        * Gets Integer representation of Overloade Duration Value.
+        * 
+        * @return int
+        */
+       public int getValue() {
+               return this.value;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + this.value;
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final OverloadedDurationTlv other = (OverloadedDurationTlv) obj;
+               if (this.value != other.value)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("OverloadedDurationTlv [value=");
+               builder.append(this.value);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/P2MPCapabilityTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/P2MPCapabilityTlv.java
new file mode 100644 (file)
index 0000000..88af019
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of P2MP Capability Tlv.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc6006#section-3.1.2">3.1.2. Open
+ *      Message Extension [RFC6006]</a>
+ */
+public class P2MPCapabilityTlv implements PCEPTlv {
+    private static final long serialVersionUID = -7959631526276210055L;
+
+    private final int value;
+
+    /**
+     * Constructs new P2MP Capability Tlv.
+     */
+    public P2MPCapabilityTlv(int value) {
+       if (value < 0 || value > 65535)
+           throw new IllegalArgumentException("Value (" + value + ") cannot be negative or bigger than 2^16 -1.");
+
+       this.value = value;
+    }
+
+    /**
+     * Constructs new P2MP Capability Tlv, with value defaultly set to zero as
+     * mentioned in RFC6006.
+     */
+    public P2MPCapabilityTlv() {
+       this.value = 0;
+    }
+
+    /**
+     * Gets integer value of P2MP Capability Tlv.
+     * 
+     * @return int
+     */
+    public int getValue() {
+       return this.value;
+    }
+
+    @Override
+    public int hashCode() {
+       final int prime = 31;
+       int result = 1;
+       result = prime * result + this.value;
+       return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+       if (this == obj)
+           return true;
+       if (obj == null)
+           return false;
+       if (this.getClass() != obj.getClass())
+           return false;
+       final P2MPCapabilityTlv other = (P2MPCapabilityTlv) obj;
+       if (this.value != other.value)
+           return false;
+       return true;
+    }
+
+    @Override
+    public String toString() {
+       final StringBuilder builder = new StringBuilder();
+       builder.append("P2MPCapablityTlv [value=");
+       builder.append(this.value);
+       builder.append("]");
+       return builder.toString();
+    }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/PCEStatefulCapabilityTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/PCEStatefulCapabilityTlv.java
new file mode 100644 (file)
index 0000000..b5ef16a
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of PCE Stateful Capability Tlv.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-8.6">STATEFUL-PCE-CAPABILITY
+ *      TLV</a>
+ * @see <a
+ *             href="http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt#section-4.1">Stateful PCE Capability
+ *             TLV</a>
+ *
+ */
+public class PCEStatefulCapabilityTlv implements PCEPTlv {
+
+       private static final long serialVersionUID = 5567589958323130325L;
+
+       private final boolean update;
+
+       private final boolean versioned;
+
+       private final boolean instantiated;
+
+       /**
+        * Constructs PCE Stateful Capability Tlv
+        *
+        * @param update
+        *            boolean
+        * @param versioned
+        *            boolean
+        */
+       public PCEStatefulCapabilityTlv(boolean instantiated, boolean update, boolean versioned) {
+               this.instantiated = instantiated;
+               this.update = update;
+               this.versioned = versioned;
+       }
+
+       /**
+        * Setting of Instantiated flag.
+        *
+        * @return boolean
+        */
+       public boolean isInstantiated() {
+               return this.instantiated;
+       }
+
+       /**
+        * Setting of Update flag.
+        *
+        * @return boolean
+        */
+       public boolean isUpdate() {
+               return this.update;
+       }
+
+       /**
+        * Setting of Versioned flag.
+        *
+        * @return boolean
+        */
+       public boolean isVersioned() {
+               return this.versioned;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (this.instantiated ? 1231 : 1237);
+               result = prime * result + (this.update ? 1231 : 1237);
+               result = prime * result + (this.versioned ? 1231 : 1237);
+               return result;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof PCEStatefulCapabilityTlv))
+                       return false;
+               final PCEStatefulCapabilityTlv other = (PCEStatefulCapabilityTlv) obj;
+               if (this.instantiated != other.instantiated)
+                       return false;
+               if (this.update != other.update)
+                       return false;
+               if (this.versioned != other.versioned)
+                       return false;
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEStatefulCapabilityTlv [update=");
+               builder.append(this.update);
+               builder.append(", versioned=");
+               builder.append(this.versioned);
+               builder.append(", instantiated=");
+               builder.append(this.instantiated);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/RSVPErrorSpecTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/RSVPErrorSpecTlv.java
new file mode 100644 (file)
index 0000000..9da45a5
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of RSVP Error Spec Tlv.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc2205">Apendix A.5: ERROR_SPEC
+ *      Class</a>
+ * @param <T>
+ */
+public class RSVPErrorSpecTlv<T extends NetworkAddress<T>> implements PCEPTlv {
+       private static final long serialVersionUID = 3948879942549682846L;
+
+       private final T errorNodeAddress;
+
+       private final boolean inPlace;
+
+       private final boolean guilty;
+
+       private final int errorCode;
+
+       private final int errorValue;
+
+       /**
+        * 
+        * Constructs new RSVP Error Spec Tlv.
+        * 
+        * @param errorNodeAddress
+        *            T
+        * @param inPlace
+        *            boolean
+        * @param guilty
+        *            boolean
+        * @param errorCode
+        *            int
+        * @param errorValue
+        *            int
+        */
+       public RSVPErrorSpecTlv(T errorNodeAddress, boolean inPlace, boolean guilty, int errorCode, int errorValue) {
+               this.errorNodeAddress = errorNodeAddress;
+               this.inPlace = inPlace;
+               this.guilty = guilty;
+               this.errorCode = errorCode;
+               this.errorValue = errorValue;
+       }
+
+       /**
+        * Gets {@link NetworkAddress} of Error Node.
+        * 
+        * @return T
+        */
+       public T getErrorNodeAddress() {
+               return this.errorNodeAddress;
+       }
+
+       /**
+        * Setting of InPlace flag.
+        * 
+        * @return boolean
+        */
+       public boolean isInPlace() {
+               return this.inPlace;
+       }
+
+       /**
+        * Setting of Guilty flag.
+        * 
+        * @return boolean
+        */
+       public boolean isGuilty() {
+               return this.guilty;
+       }
+
+       /**
+        * Gets int representation of Error Code.
+        * 
+        * @return int
+        */
+       public int getErrorCode() {
+               return this.errorCode;
+       }
+
+       /**
+        * Gets int representation of Error Value.
+        * 
+        * @return int
+        */
+       public int getErrorValue() {
+               return this.errorValue;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + this.errorCode;
+               result = prime * result + ((this.errorNodeAddress == null) ? 0 : this.errorNodeAddress.hashCode());
+               result = prime * result + this.errorValue;
+               result = prime * result + (this.guilty ? 1231 : 1237);
+               result = prime * result + (this.inPlace ? 1231 : 1237);
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final RSVPErrorSpecTlv<?> other = (RSVPErrorSpecTlv<?>) obj;
+               if (this.errorCode != other.errorCode)
+                       return false;
+               if (this.errorNodeAddress == null) {
+                       if (other.errorNodeAddress != null)
+                               return false;
+               } else if (!this.errorNodeAddress.equals(other.errorNodeAddress))
+                       return false;
+               if (this.errorValue != other.errorValue)
+                       return false;
+               if (this.guilty != other.guilty)
+                       return false;
+               if (this.inPlace != other.inPlace)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("RSVPErrorSpecTlv [errorNodeAddress=");
+               builder.append(this.errorNodeAddress);
+               builder.append(", inPlace=");
+               builder.append(this.inPlace);
+               builder.append(", guilty=");
+               builder.append(this.guilty);
+               builder.append(", errorCode=");
+               builder.append(this.errorCode);
+               builder.append(", errorValue=");
+               builder.append(this.errorValue);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/ReqMissingTlv.java b/pcep/api/src/main/java/org/opendaylight/protocol/pcep/tlv/ReqMissingTlv.java
new file mode 100644 (file)
index 0000000..b8357fa
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of Request Missing Tlv.
+ * 
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.15">PCEP-ERROR
+ *      Object</a> - defined in text (Error-type=7)
+ */
+public class ReqMissingTlv implements PCEPTlv {
+       private static final long serialVersionUID = -3910927830017195746L;
+       private final long requestID;
+
+       /**
+        * Constructs new Request Missing Tlv.
+        * 
+        * @param requestID
+        *            long
+        */
+       public ReqMissingTlv(long requestID) {
+               this.requestID = requestID;
+       }
+
+       /**
+        * gets long representation of Requested ID.
+        * 
+        * @return long
+        */
+       public long getRequestID() {
+               return this.requestID;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (int) (this.requestID ^ (this.requestID >>> 32));
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final ReqMissingTlv other = (ReqMissingTlv) obj;
+               if (this.requestID != other.requestID)
+                       return false;
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("ReqMissingTlv [requestID=");
+               builder.append(this.requestID);
+               builder.append("]");
+               return builder.toString();
+       }
+
+}
diff --git a/pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/APITest.java b/pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/APITest.java
new file mode 100644 (file)
index 0000000..ec75984
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ *
+ */
+public class APITest {
+
+       @Test
+       public void testDeserializerException() {
+               final PCEPDeserializerException e = new PCEPDeserializerException("Some error message.");
+               assertEquals("Some error message.", e.getErrorMessage());
+
+               final PCEPDeserializerException e1 = new PCEPDeserializerException(new IllegalArgumentException(), "Some error message.");
+               assertEquals("Some error message.", e1.getErrorMessage());
+               assertTrue(e1.getCause() instanceof IllegalArgumentException);
+       }
+
+       @Test
+       public void testDocumentedException() throws PCEPDocumentedException {
+               final PCEPDocumentedException de = new PCEPDocumentedException("", PCEPErrors.C_BIT_SET);
+               assertEquals(PCEPErrors.C_BIT_SET, de.getError());
+       }
+
+       @Test
+       public void testPCEPMessage() {
+               final List<PCEPObject> objs = new ArrayList<PCEPObject>();
+               objs.add(new PCEPErrorObject(PCEPErrors.ATTEMPT_2ND_SESSION));
+               final PCEPMessage msg1 = new PCEPMessage(objs) {
+                       private static final long serialVersionUID = 1L;
+               };
+               final PCEPMessage msg2 = new PCEPMessage(objs) {
+                       private static final long serialVersionUID = 1L;
+               };
+
+               assertNotSame(msg1, msg2); //not same because they are anonymous classes
+               assertEquals(msg1.hashCode(), msg2.hashCode());
+               assertEquals(msg1.toString(), msg2.toString());
+       }
+
+       @Test
+       public void testPCEPObject() {
+               final PCEPObject obj1 = new PCEPObject(true, false) {
+               };
+               final PCEPObject obj2 = new PCEPErrorObject(PCEPErrors.CANNOT_PROCESS_STATE_REPORT);
+               final PCEPObject obj4 = new PCEPObject(true, false) {
+               };
+
+               assertNotSame(obj1, obj2);
+               assertNotSame(obj1, obj4);
+               assertEquals(obj1.hashCode(), obj4.hashCode());
+               assertEquals(obj1.toString(), obj4.toString());
+
+       }
+
+       @Test
+       public void testSubobject() {
+               final ExplicitRouteSubobject sub1 = new EROAsNumberSubobject(new ASNumber(100), true);
+               final ExplicitRouteSubobject sub2 = new ExplicitRouteSubobject(false) {
+               };
+               final ExplicitRouteSubobject sub3 = new ExplicitRouteSubobject(false) {
+               };
+               final ExplicitRouteSubobject sub4 = new EROAsNumberSubobject(new ASNumber(100), true);
+
+               assertNotSame(sub1, sub2);
+               assertNotSame(sub2, sub3);
+               assertEquals(sub1, sub4);
+               assertNotSame(sub2, sub3);
+               assertEquals(sub1.hashCode(), sub4.hashCode());
+               assertEquals(sub2.toString(), sub3.toString());
+       }
+}
diff --git a/pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/ConceptsTest.java b/pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/ConceptsTest.java
new file mode 100644 (file)
index 0000000..e599a9e
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.api;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.concepts.AbstractExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.AggregateBandwidthConsumptionMetric;
+import org.opendaylight.protocol.pcep.concepts.CumulativeIGPCostMetric;
+import org.opendaylight.protocol.pcep.concepts.CumulativeTECostMetric;
+import org.opendaylight.protocol.pcep.concepts.IPv4ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.IPv6ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+import org.opendaylight.protocol.pcep.concepts.MostLoadedLinkLoadMetric;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+
+public class ConceptsTest {
+
+       @Test
+       public void testConcepts() throws UnknownHostException {
+               final AbstractExtendedTunnelIdentifier<IPv4Address> t1 = new AbstractExtendedTunnelIdentifier<IPv4Address>(new IPv4Address(
+                               InetAddress.getByName("127.0.0.1"))) {
+                       private static final long serialVersionUID = 445350555352830607L;
+               };
+
+               final AbstractExtendedTunnelIdentifier<IPv4Address> t2 = new AbstractExtendedTunnelIdentifier<IPv4Address>(new IPv4Address(
+                               InetAddress.getByName("127.0.0.2"))) {
+                       private static final long serialVersionUID = 572633522583009640L;
+               };
+
+               final AbstractExtendedTunnelIdentifier<IPv4Address> t3 = new AbstractExtendedTunnelIdentifier<IPv4Address>(new IPv4Address(
+                               InetAddress.getByName("127.0.0.1"))) {
+                       private static final long serialVersionUID = 445350555352830607L;
+               };
+
+               assertNotSame(t1, t2);
+               assertEquals(-1, t1.compareTo(t2));
+               assertEquals(t1.hashCode(), t3.hashCode());
+               assertEquals(t1.toString(), t3.toString());
+
+               final IPv4ExtendedTunnelIdentifier v4 = new IPv4ExtendedTunnelIdentifier(new IPv4Address(InetAddress.getByName("127.0.0.1")));
+               final IPv6ExtendedTunnelIdentifier v6 = new IPv6ExtendedTunnelIdentifier(new IPv6Address(InetAddress.getByName("2001:db8:85a3::8a2e:370:7333")));
+               assertTrue(v4 instanceof AbstractExtendedTunnelIdentifier);
+               assertTrue(v6 instanceof AbstractExtendedTunnelIdentifier);
+
+               final LSPIdentifier id1 = new LSPIdentifier(new byte[] { 1, 2 });
+               final LSPIdentifier id2 = new LSPIdentifier(new byte[] { 1, 3 });
+               final LSPIdentifier id3 = new LSPIdentifier(new byte[] { 1, 3 });
+
+               assertNotSame(id1, id2);
+               assertNotSame(id1.getLspId(), id2.getLspId());
+               assertEquals(id3.toString(), id2.toString());
+
+               final LSPSymbolicName n1 = new LSPSymbolicName(new byte[] { 5 });
+               final LSPSymbolicName n2 = new LSPSymbolicName(new byte[] { 6, 3 });
+               final LSPSymbolicName n3 = new LSPSymbolicName(new byte[] { 5 });
+               assertNotSame(n1.getSymbolicName(), n2.getSymbolicName());
+               assertEquals(n1, n3);
+               assertEquals(n1.toString(), n3.toString());
+
+               final TunnelIdentifier ti1 = new TunnelIdentifier(new byte[] { 2, 4 });
+               final TunnelIdentifier ti2 = new TunnelIdentifier(new byte[] { 2, 4 });
+               assertArrayEquals(ti1.getBytes(), ti2.getBytes());
+               assertEquals(ti1, ti2);
+               assertEquals(ti1.toString(), ti2.toString());
+
+               final UnnumberedInterfaceIdentifier u1 = new UnnumberedInterfaceIdentifier(3000);
+               final UnnumberedInterfaceIdentifier u2 = new UnnumberedInterfaceIdentifier(4000);
+               final UnnumberedInterfaceIdentifier u3 = new UnnumberedInterfaceIdentifier(3000);
+
+               assertEquals(-1, u1.compareTo(u2));
+               assertEquals(u1, u3);
+               assertEquals(u1.hashCode(), u3.hashCode());
+               assertEquals(u1.getInterfaceId(), u3.getInterfaceId());
+               assertEquals(u1.toString(), u3.toString());
+
+               final CumulativeIGPCostMetric cigp1 = new CumulativeIGPCostMetric(3000);
+               final CumulativeIGPCostMetric cigp2 = new CumulativeIGPCostMetric(4000);
+               final CumulativeIGPCostMetric cigp3 = new CumulativeIGPCostMetric(3000);
+               try {
+                       new CumulativeIGPCostMetric(-1);
+                       fail("Expected exception but no thrown.");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               assertEquals(-1, cigp1.compareTo(cigp2));
+               assertEquals(cigp1, cigp3);
+               assertEquals(cigp1.hashCode(), cigp3.hashCode());
+               assertEquals(cigp1.getValue(), cigp3.getValue());
+               assertEquals(cigp1.toString(), cigp3.toString());
+
+               final CumulativeTECostMetric cte1 = new CumulativeTECostMetric(3000);
+               final CumulativeTECostMetric cte2 = new CumulativeTECostMetric(4000);
+               final CumulativeTECostMetric cte3 = new CumulativeTECostMetric(3000);
+
+               assertEquals(-1, cte1.compareTo(cte2));
+               assertEquals(cte1, cte3);
+               assertEquals(cte1.hashCode(), cte3.hashCode());
+               assertEquals(cte1.getValue(), cte3.getValue());
+               assertEquals(cte1.toString(), cte3.toString());
+               try {
+                       new CumulativeTECostMetric(-1);
+                       fail("Expected exception but no thrown.");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               final AggregateBandwidthConsumptionMetric agg1 = new AggregateBandwidthConsumptionMetric(3000);
+               final AggregateBandwidthConsumptionMetric agg2 = new AggregateBandwidthConsumptionMetric(4000);
+               final AggregateBandwidthConsumptionMetric agg3 = new AggregateBandwidthConsumptionMetric(3000);
+
+               assertEquals(-1, agg1.compareTo(agg2));
+               assertEquals(agg1, agg3);
+               assertEquals(agg1.hashCode(), agg3.hashCode());
+               assertEquals(agg1.getValue(), agg3.getValue());
+               assertEquals(agg1.toString(), agg3.toString());
+               try {
+                       new AggregateBandwidthConsumptionMetric(-1);
+                       fail("Expected exception but no thrown.");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               final MostLoadedLinkLoadMetric mlm1 = new MostLoadedLinkLoadMetric(3000);
+               final MostLoadedLinkLoadMetric mlm2 = new MostLoadedLinkLoadMetric(4000);
+               final MostLoadedLinkLoadMetric mlm3 = new MostLoadedLinkLoadMetric(3000);
+
+               assertEquals(-1, mlm1.compareTo(mlm2));
+               assertEquals(mlm1, mlm3);
+               assertEquals(mlm1.hashCode(), mlm3.hashCode());
+               assertEquals(mlm1.getValue(), mlm3.getValue());
+               assertEquals(mlm1.toString(), mlm3.toString());
+               try {
+                       new MostLoadedLinkLoadMetric(-1);
+                       fail("Expected exception but no thrown.");
+               } catch (final IllegalArgumentException e) {
+               }
+       }
+}
diff --git a/pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/MessagesTest.java b/pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/MessagesTest.java
new file mode 100644 (file)
index 0000000..b633e9f
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+
+public class MessagesTest {
+
+       @Test
+       public void errorMessageTest() {
+               final List<PCEPErrorObject> errorObjs = new ArrayList<PCEPErrorObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new PCEPErrorObject(PCEPErrors.ATTEMPT_2ND_SESSION));
+                               this.add(new PCEPErrorObject(PCEPErrors.ATTEMPT_2ND_SESSION));
+                       }
+               };
+               final List<CompositeErrorObject> errors = new ArrayList<CompositeErrorObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeErrorObject(errorObjs));
+                       }
+               };
+
+               final List<?> objs = new ArrayList<Object>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeErrorObject(errorObjs));
+                               this.add(new PCEPErrorObject(PCEPErrors.BANDWIDTH_MISSING));
+                       }
+               };
+
+               final PCEPErrorMessage m = new PCEPErrorMessage(new PCEPOpenObject(10, 10, 1), errorObjs, errors);
+               final PCEPErrorMessage m2 = new PCEPErrorMessage(new PCEPOpenObject(10, 10, 1), errorObjs, errors);
+               final PCEPErrorMessage m3 = new PCEPErrorMessage(objs);
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getOpenObject(), m2.getOpenObject());
+               assertEquals(m.getErrors(), m2.getErrors());
+               assertEquals(m.getErrorObjects(), m2.getErrorObjects());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPCloseMessage(new PCEPCloseObject(Reason.EXP_DEADTIMER))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void closeMessageTest() {
+               final PCEPCloseMessage m = new PCEPCloseMessage(new PCEPCloseObject(Reason.EXP_DEADTIMER));
+               final PCEPCloseMessage m2 = new PCEPCloseMessage(new PCEPCloseObject(Reason.EXP_DEADTIMER));
+               final PCEPCloseMessage m3 = new PCEPCloseMessage(new PCEPCloseObject(Reason.MALFORMED_MSG));
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getCloseObject(), m2.getCloseObject());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+
+               new PCEPCloseMessage(null);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void openMessageTest() {
+               final PCEPOpenMessage m = new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1));
+               final PCEPOpenMessage m2 = new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1));
+               final PCEPOpenMessage m3 = new PCEPOpenMessage(new PCEPOpenObject(5, 5, 1));
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getOpenObject(), m2.getOpenObject());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPCloseMessage(new PCEPCloseObject(Reason.EXP_DEADTIMER))));
+               assertTrue(m.equals(m));
+
+               new PCEPOpenMessage(null);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void keepAliveMessageTest() {
+               final PCEPKeepAliveMessage m = new PCEPKeepAliveMessage();
+               final PCEPKeepAliveMessage m2 = new PCEPKeepAliveMessage();
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(new PCEPCloseMessage(new PCEPCloseObject(Reason.EXP_DEADTIMER))));
+               assertTrue(m.equals(m));
+
+               new PCEPOpenMessage(null);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void notifyMessageTest() {
+               final List<CompositeNotifyObject> notifications = new ArrayList<CompositeNotifyObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeNotifyObject(new ArrayList<PCEPNotificationObject>() {
+                                       private static final long serialVersionUID = 1L;
+
+                                       {
+                                               this.add(new PCEPNotificationObject((short) 2, (short) 3));
+                                       }
+                               }));
+                       }
+               };
+
+               final PCEPNotificationMessage m = new PCEPNotificationMessage(notifications);
+               final PCEPNotificationMessage m2 = new PCEPNotificationMessage(notifications);
+               final PCEPNotificationMessage m3 = new PCEPNotificationMessage(new ArrayList<CompositeNotifyObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeNotifyObject(new ArrayList<PCEPNotificationObject>() {
+                                       private static final long serialVersionUID = 1L;
+
+                                       {
+                                               this.add(new PCEPNotificationObject((short) 2, (short) 5));
+                                       }
+                               }));
+                       }
+               });
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getNotifications(), m2.getNotifications());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+
+               new PCEPNotificationMessage(null);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void replyMessageTest() {
+               final List<CompositeResponseObject> replies = new ArrayList<CompositeResponseObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false, (short) 1, 1, true,
+                                               false)));
+                       }
+               };
+
+               final PCEPReplyMessage m = new PCEPReplyMessage(replies);
+               final PCEPReplyMessage m2 = new PCEPReplyMessage(replies);
+               final PCEPReplyMessage m3 = new PCEPReplyMessage(new ArrayList<CompositeResponseObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, false, true, false, false, false, (short) 2, 1, false,
+                                               false)));
+                       }
+               });
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getResponses(), m2.getResponses());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+
+               new PCEPReplyMessage(null);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void reportMessageTest() {
+               final List<CompositeStateReportObject> reports = new ArrayList<CompositeStateReportObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeStateReportObject(new PCEPLspObject(1, true, true, true, true)));
+                       }
+               };
+
+               final PCEPReportMessage m = new PCEPReportMessage(reports);
+               final PCEPReportMessage m2 = new PCEPReportMessage(reports);
+               final PCEPReportMessage m3 = new PCEPReportMessage(new ArrayList<CompositeStateReportObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeStateReportObject(new PCEPLspObject(5, false, true, true, true)));
+                       }
+               });
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getStateReports(), m2.getStateReports());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+
+               new PCEPReportMessage(null);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void requestMessageTest() {
+               final List<CompositeRequestObject> reports = new ArrayList<CompositeRequestObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeRequestObject(
+                                               new PCEPRequestParameterObject(true, true, true, true, true, false, false, false, (short) 5, 5, true, true),
+                                               new PCEPEndPointsObject<IPv4Address>(
+                                                       new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 }),
+                                                       new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 }))));
+                       }
+               };
+
+               final PCEPRequestMessage m = new PCEPRequestMessage(reports);
+               final PCEPRequestMessage m2 = new PCEPRequestMessage(reports);
+               final PCEPRequestMessage m3 = new PCEPRequestMessage(new ArrayList<CompositeRequestObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeRequestObject(
+                                               new PCEPRequestParameterObject(true, true, true, false, true, false, false, false, (short) 5, 5, true, true),
+                                               new PCEPEndPointsObject<IPv4Address>(
+                                                       new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }),
+                                                       new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 }))));
+                       }
+               });
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getSvecObjects(), m2.getSvecObjects());
+               assertEquals(m.getRequests(), m2.getRequests());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+
+               new PCEPRequestMessage(null);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void updateRequestMessageTest() {
+               final List<CompositeUpdateRequestObject> reports = new ArrayList<CompositeUpdateRequestObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, true, true, true)));
+                       }
+               };
+
+               final PCEPUpdateRequestMessage m = new PCEPUpdateRequestMessage(reports);
+               final PCEPUpdateRequestMessage m2 = new PCEPUpdateRequestMessage(reports);
+               final PCEPUpdateRequestMessage m3 = new PCEPUpdateRequestMessage(new ArrayList<CompositeUpdateRequestObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeUpdateRequestObject(new PCEPLspObject(5, true, true, true, true)));
+                       }
+               });
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getUpdateRequests(), m2.getUpdateRequests());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+
+               new PCEPUpdateRequestMessage(null);
+       }
+}
diff --git a/pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/ObjectsTest.java b/pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/ObjectsTest.java
new file mode 100644 (file)
index 0000000..00ec009
--- /dev/null
@@ -0,0 +1,748 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.CompositePathObject;
+import org.opendaylight.protocol.pcep.object.CompositeReplySvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestSvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+import org.opendaylight.protocol.pcep.object.CompositeRptPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+import org.opendaylight.protocol.pcep.object.PCEPBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPClassTypeObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPoints;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSubobjectAttribute;
+import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.tlv.OrderTlv;
+import com.google.common.collect.Lists;
+
+/**
+ *
+ */
+public class ObjectsTest {
+
+    @Test
+    public void compositeErrorObjectTest() {
+
+       final List<PCEPErrorObject> errorObjects = new ArrayList<PCEPErrorObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new PCEPErrorObject(PCEPErrors.ATTEMPT_2ND_SESSION));
+           }
+       };
+
+       final List<PCEPRequestParameterObject> errorParams = new ArrayList<PCEPRequestParameterObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false, (short) 1, 1, true, true));
+           }
+       };
+       final CompositeErrorObject m = new CompositeErrorObject(errorParams, errorObjects);
+       final CompositeErrorObject m2 = new CompositeErrorObject(errorParams, errorObjects);
+       final CompositeErrorObject m3 = new CompositeErrorObject(errorObjects);
+
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getErrors(), m2.getErrors());
+       assertEquals(m.getRequestParameters(), m2.getRequestParameters());
+       assertEquals(m, CompositeErrorObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void compositeNotifyObjectTest() {
+
+       final List<PCEPNotificationObject> notifications = new ArrayList<PCEPNotificationObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new PCEPNotificationObject((short) 2, (short) 3));
+           }
+       };
+
+       final List<PCEPRequestParameterObject> reqParams = new ArrayList<PCEPRequestParameterObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false, (short) 1, 1, true, true));
+           }
+       };
+       final CompositeNotifyObject m = new CompositeNotifyObject(reqParams, notifications);
+       final CompositeNotifyObject m2 = new CompositeNotifyObject(reqParams, notifications);
+       final CompositeNotifyObject m3 = new CompositeNotifyObject(notifications);
+
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getNotificationObjects(), m2.getNotificationObjects());
+       assertEquals(m.getRequestParameters(), m2.getRequestParameters());
+       assertEquals(m, CompositeNotifyObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void compositePathObjectTest() {
+
+       final List<ExplicitRouteSubobject> subobjects = new ArrayList<ExplicitRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+           }
+       };
+
+       final CompositePathObject m = new CompositePathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2,
+               true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+           }
+       }, new PCEPIncludeRouteObject(subobjects, true, true));
+       final CompositePathObject m2 = new CompositePathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2,
+               true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+           }
+       }, new PCEPIncludeRouteObject(subobjects, true, true));
+       final CompositePathObject m3 = new CompositePathObject(new PCEPExplicitRouteObject(subobjects, false));
+
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getBandwidth(), m2.getBandwidth());
+       assertEquals(m.getExcludedRoute(), m2.getExcludedRoute());
+       assertEquals(m.getIncludeRoute(), m2.getIncludeRoute());
+       assertEquals(m.getLspa(), m2.getLspa());
+       assertEquals(m.getMetrics(), m2.getMetrics());
+       assertEquals(m, CompositePathObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void compositeRptPathObjectTest() {
+
+       final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new EROUnnumberedInterfaceSubobject(new IPv4Address(
+                       new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new UnnumberedInterfaceIdentifier(2), true));
+               this.add(new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(
+                       new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22), false));
+           }
+       };
+
+       final List<ReportedRouteSubobject> rroSubobjects = new ArrayList<ReportedRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new RROUnnumberedInterfaceSubobject(new IPv4Address(
+                       new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new UnnumberedInterfaceIdentifier(2)));
+               this.add(new RROIPAddressSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(
+                       new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22), true, false));
+           }
+       };
+
+       final CompositeRptPathObject m = new CompositeRptPathObject(new PCEPExplicitRouteObject(eroSubobjects, false), new PCEPLspaObject(2, 2, 2, (short) 2,
+               (short) 2, true, true, true, true), new PCEPExistingPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+               new PCEPReportedRouteObject(rroSubobjects, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+                   }
+               });
+       final CompositeRptPathObject m2 = new CompositeRptPathObject(new PCEPExplicitRouteObject(eroSubobjects, false), new PCEPLspaObject(2, 2, 2, (short) 2,
+               (short) 2, true, true, true, true), new PCEPExistingPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+               new PCEPReportedRouteObject(rroSubobjects, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+                   }
+               });
+       final CompositePathObject m3 = new CompositePathObject(new PCEPExplicitRouteObject(eroSubobjects, false));
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getBandwidth(), m2.getBandwidth());
+       assertEquals(m.getExcludedRoute(), m2.getExcludedRoute());
+       assertEquals(m.getLspa(), m2.getLspa());
+       assertEquals(m.getMetrics(), m2.getMetrics());
+       assertEquals(m, CompositeRptPathObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void compositeUpdPathObjectTest() {
+
+       final List<ExplicitRouteSubobject> subobjects = new ArrayList<ExplicitRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+           }
+       };
+
+       final CompositeUpdPathObject m = new CompositeUpdPathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2,
+               (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+               new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+                   }
+               });
+       final CompositeUpdPathObject m2 = new CompositeUpdPathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2,
+               (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+               new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+                   }
+               });
+       final CompositeUpdPathObject m3 = new CompositeUpdPathObject(new PCEPExplicitRouteObject(subobjects, false));
+
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getBandwidth(), m2.getBandwidth());
+       assertEquals(m.getExcludedRoute(), m2.getExcludedRoute());
+       assertEquals(m.getLspa(), m2.getLspa());
+       assertEquals(m.getMetrics(), m2.getMetrics());
+       assertEquals(m, CompositeUpdPathObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void compositeRequestedObjectTest() {
+
+       final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+           }
+       };
+
+       final List<ReportedRouteSubobject> rroSubobjects = new ArrayList<ReportedRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new RROAsNumberSubobject(new ASNumber(2555)));
+           }
+       };
+
+       final CompositeRequestObject m = new CompositeRequestObject(new PCEPRequestParameterObject(true, true, true, true, true, true, false, false, false,
+               (short) 1, 1, new ArrayList<PCEPTlv>() {
+                   private static final long serialVersionUID = 1L;
+                   {
+                       this.add(new OrderTlv(1L, 2L));
+                   }
+               }, true, true), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(
+               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new IPv4Address(
+               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 })), new PCEPClassTypeObject((short) 2), new PCEPLspObject((short) 1, true, true, true,
+               true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth(
+               (float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+           }
+       }, new PCEPReportedRouteObject(rroSubobjects, true), new PCEPExistingPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+               new PCEPIncludeRouteObject(eroSubobjects, true, true), new PCEPLoadBalancingObject(2, new Bandwidth((float) 0.2), true));
+       final CompositeRequestObject m2 = new CompositeRequestObject(new PCEPRequestParameterObject(true, true, true, true, true, true, false, false, false,
+               (short) 1, 1, new ArrayList<PCEPTlv>() {
+                   private static final long serialVersionUID = 1L;
+                   {
+                       this.add(new OrderTlv(1L, 2L));
+                   }
+               }, true, true), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(
+               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new IPv4Address(
+               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 })), new PCEPClassTypeObject((short) 2), new PCEPLspObject((short) 1, true, true, true,
+               true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth(
+               (float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+           }
+       }, new PCEPReportedRouteObject(rroSubobjects, true), new PCEPExistingPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+               new PCEPIncludeRouteObject(eroSubobjects, true, true), new PCEPLoadBalancingObject(2, new Bandwidth((float) 0.2), true));
+       final CompositeRequestObject m3 = new CompositeRequestObject(new PCEPRequestParameterObject(true, true, true, true, true, true, false, false, false,
+               (short) 1, 1, new ArrayList<PCEPTlv>() {
+                   private static final long serialVersionUID = 1L;
+                   {
+                       this.add(new OrderTlv(1L, 2L));
+                   }
+               }, true, true), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(
+               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new IPv4Address(
+               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 })));
+
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getBandwidth(), m2.getBandwidth());
+       assertEquals(m.getLspa(), m2.getLspa());
+       assertEquals(m.getMetrics(), m2.getMetrics());
+       assertEquals(m.getClassType(), m2.getClassType());
+       assertEquals(m.getEndPoints(), m2.getEndPoints());
+       assertEquals(m.getIncludeRoute(), m2.getIncludeRoute());
+       assertEquals(m.getLsp(), m2.getLsp());
+       assertEquals(m.getRroBandwidth(), m2.getRroBandwidth());
+       assertEquals(m, CompositeRequestObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void compositeResponseObjectTest() {
+
+       final List<ExplicitRouteSubobject> subobjects = new ArrayList<ExplicitRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+           }
+       };
+
+       final List<CompositePathObject> paths = new ArrayList<CompositePathObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new CompositePathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true, true,
+                       true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+                   }
+               }, new PCEPIncludeRouteObject(subobjects, true, true)));
+           }
+       };
+
+       final CompositeResponseObject m = new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false,
+               (short) 1, 1, true, true), new PCEPNoPathObject((short) 2, true, false), new PCEPLspObject((short) 1, true, true, true, true),
+               new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222),
+                       true, true), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+                   }
+               }, new PCEPIncludeRouteObject(subobjects, true, true), paths);
+       final CompositeResponseObject m2 = new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false,
+               (short) 1, 1, true, true), new PCEPNoPathObject((short) 2, true, false), new PCEPLspObject((short) 1, true, true, true, true),
+               new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222),
+                       true, true), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+                   }
+               }, new PCEPIncludeRouteObject(subobjects, true, true), paths);
+       final CompositeResponseObject m3 = new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false,
+               (short) 1, 1, true, true));
+
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getBandwidth(), m2.getBandwidth());
+       assertEquals(m.getLspa(), m2.getLspa());
+       assertEquals(m.getMetrics(), m2.getMetrics());
+       assertEquals(m.getIncludeRoute(), m2.getIncludeRoute());
+       assertEquals(m.getLsp(), m2.getLsp());
+       assertEquals(m.getPaths(), m2.getPaths());
+       assertEquals(m.getRequestParameter(), m2.getRequestParameter());
+       assertEquals(m, CompositeResponseObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void compositeStateReportObjectTest() {
+
+       final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+           }
+       };
+
+       final List<ReportedRouteSubobject> rroSubobjects = new ArrayList<ReportedRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new RROAsNumberSubobject(new ASNumber(2555)));
+           }
+       };
+
+       final List<CompositeRptPathObject> paths = new ArrayList<CompositeRptPathObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(eroSubobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true,
+                       true, true, true), new PCEPExistingPathBandwidthObject(new Bandwidth((float) 0.222), true, true), new PCEPReportedRouteObject(
+                       rroSubobjects, true), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+                   }
+               }));
+           }
+       };
+
+       final CompositeStateReportObject m = new CompositeStateReportObject(new PCEPLspObject((short) 1, true, true, true, true), paths);
+       final CompositeStateReportObject m2 = new CompositeStateReportObject(new PCEPLspObject((short) 1, true, true, true, true), paths);
+       final CompositeStateReportObject m3 = new CompositeStateReportObject(new PCEPLspObject((short) 1, true, true, true, true));
+
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getLsp(), m2.getLsp());
+       assertEquals(m.getPaths(), m2.getPaths());
+       assertEquals(m, CompositeStateReportObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void compositeUpdateRequestObjectTest() {
+
+       final List<ExplicitRouteSubobject> subobjects = new ArrayList<ExplicitRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+           }
+       };
+
+       final List<CompositeUpdPathObject> paths = new ArrayList<CompositeUpdPathObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true,
+                       true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+                   }
+               }));
+           }
+       };
+
+       final CompositeUpdateRequestObject m = new CompositeUpdateRequestObject(new PCEPLspObject((short) 1, true, true, true, true), paths);
+       final CompositeUpdateRequestObject m2 = new CompositeUpdateRequestObject(new PCEPLspObject((short) 1, true, true, true, true), paths);
+       final CompositeUpdateRequestObject m3 = new CompositeUpdateRequestObject(new PCEPLspObject((short) 1, true, true, true, true));
+
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getLsp(), m2.getLsp());
+       assertEquals(m.getPaths(), m2.getPaths());
+       assertEquals(m, CompositeUpdateRequestObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void compositeRequestSVECObjectTest() {
+
+       final List<ExcludeRouteSubobject> subobjects = new ArrayList<ExcludeRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new XROAsNumberSubobject(new ASNumber(2555), false));
+           }
+       };
+
+       final List<Long> requestIds = new ArrayList<Long>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(0x12345678L);
+           }
+       };
+
+       final CompositeRequestSvecObject m = new CompositeRequestSvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true),
+               new PCEPObjectiveFunctionObject(PCEPOFCodes.MBC, true, false), new PCEPGlobalConstraintsObject((short) 2, (short) 2, (short) 2, (short) 2,
+                       true, false), new PCEPExcludeRouteObject(subobjects, true, true, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(0x123456), true, false));
+                   }
+               });
+       final CompositeRequestSvecObject m2 = new CompositeRequestSvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true),
+               new PCEPObjectiveFunctionObject(PCEPOFCodes.MBC, true, false), new PCEPGlobalConstraintsObject((short) 2, (short) 2, (short) 2, (short) 2,
+                       true, false), new PCEPExcludeRouteObject(subobjects, true, true, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(0x123456), true, false));
+                   }
+               });
+       final CompositeRequestSvecObject m3 = new CompositeRequestSvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true));
+
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getExcludeRoute(), m2.getExcludeRoute());
+       assertEquals(m.getGlobalConstraints(), m2.getGlobalConstraints());
+       assertEquals(m.getObjectiveFunction(), m2.getObjectiveFunction());
+       assertEquals(m.getSvec(), m2.getSvec());
+       assertEquals(m, CompositeRequestSvecObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void compositeRplySVECObjectTest() {
+
+       final List<Long> requestIds = new ArrayList<Long>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(0x12345678L);
+           }
+       };
+
+       final CompositeReplySvecObject m = new CompositeReplySvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true),
+               new PCEPObjectiveFunctionObject(PCEPOFCodes.MBC, true, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(0x123456), true, false));
+                   }
+               });
+       final CompositeReplySvecObject m2 = new CompositeReplySvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true),
+               new PCEPObjectiveFunctionObject(PCEPOFCodes.MBC, true, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(0x123456), true, false));
+                   }
+               });
+       final CompositeReplySvecObject m3 = new CompositeReplySvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true));
+
+       assertEquals(m, m2);
+       assertEquals(m.toString(), m2.toString());
+       assertEquals(m.hashCode(), m2.hashCode());
+       assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+       assertEquals(m.getObjectiveFunction(), m2.getObjectiveFunction());
+       assertEquals(m.getSvec(), m2.getSvec());
+       assertEquals(m, CompositeReplySvecObject.getCompositeFromList(m.getCompositeAsList()));
+       assertFalse(m.equals(null));
+       assertFalse(m.equals(m3));
+       assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(m.equals(m));
+    }
+
+    @Test
+    public void subobjectsTest() {
+       final EROAsNumberSubobject as = new EROAsNumberSubobject(new ASNumber(2555), false);
+       final EROUnnumberedInterfaceSubobject uis = new EROUnnumberedInterfaceSubobject(new IPv4Address(
+               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new UnnumberedInterfaceIdentifier(2), true);
+       final EROIPPrefixSubobject<IPv4Prefix> ips = new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22), false);
+
+       assertEquals(as.getASNumber().getAsn(), 2555);
+       assertEquals(as.isLoose(), false);
+       assertFalse(as.equals(null));
+       assertFalse(as.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(as.equals(as));
+
+       assertEquals(uis.getInterfaceID().getInterfaceId(), 2);
+       assertEquals(uis.getRouterID(),
+               new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }));
+       assertEquals(uis.isLoose(), true);
+       assertFalse(uis.equals(null));
+       assertFalse(uis.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(uis.equals(uis));
+
+       assertEquals(
+               ips.getPrefix(),
+               new IPv4Prefix(new IPv4Address(new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22));
+       assertEquals(ips.isLoose(), false);
+       assertFalse(ips.equals(null));
+       assertFalse(ips.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(ips.equals(ips));
+    }
+
+    @Test
+    public void xroSubobjectsTest() {
+       final XROAsNumberSubobject as = new XROAsNumberSubobject(new ASNumber(2555), false);
+       final XROUnnumberedInterfaceSubobject uis = new XROUnnumberedInterfaceSubobject(new IPv4Address(
+               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new UnnumberedInterfaceIdentifier(2), true, XROSubobjectAttribute.SRLG);
+       final XROIPPrefixSubobject<IPv4Prefix> ips = new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22), false, XROSubobjectAttribute.SRLG);
+       final XROSRLGSubobject srlg = new XROSRLGSubobject(new SharedRiskLinkGroup(0x1234L), true);
+
+       assertEquals(as.getASNumber().getAsn(), 2555);
+       assertEquals(as.isMandatory(), false);
+       assertFalse(as.equals(null));
+       assertFalse(as.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(as.equals(as));
+       assertEquals(as.toString(), "XROAsNumberSubobject [asnumber=2555, mandatory=false]");
+
+       assertEquals(uis.getInterfaceID().getInterfaceId(), 2);
+       assertEquals(uis.getRouterID(),
+               new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }));
+       assertEquals(uis.isMandatory(), true);
+       assertFalse(uis.equals(null));
+       assertFalse(uis.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(uis.equals(uis));
+       assertEquals(uis.getAttribute(), XROSubobjectAttribute.SRLG);
+       assertEquals(uis.toString(),
+               "XROUnnumberedInterfaceSubobject [attribute=SRLG, interfaceID=UnnumberedInterfaceIdentifier [interfaceId=2], routerID=127.0.0.2, mandatory=true]");
+
+       assertEquals(
+               ips.getPrefix(),
+               new IPv4Prefix(new IPv4Address(new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22));
+       assertEquals(ips.isMandatory(), false);
+       assertFalse(ips.equals(null));
+       assertFalse(ips.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(ips.equals(ips));
+       assertEquals(ips.getAttribute(), XROSubobjectAttribute.SRLG);
+       assertEquals(ips.toString(), "XROIPPrefixSubobject [attribute=SRLG, prefix=12.122.124.0/22, mandatory=false]");
+
+       assertEquals(srlg.getSrlgId().getValue(), 0x1234L);
+       assertEquals(srlg.getAttribute(), XROSubobjectAttribute.SRLG);
+       assertFalse(srlg.equals(null));
+       assertFalse(srlg.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+       assertTrue(srlg.equals(srlg));
+       assertEquals(srlg.toString(), "XROSRLGSubobject [attribute=SRLG, srlgId=4660, mandatory=true]");
+    }
+
+    @Test
+    public void testToString(){
+       final List<PCEPObject> objects = Lists.newArrayList();
+       objects.add(new PCEPExistingPathBandwidthObject(new Bandwidth(22.0), true, false));
+       objects.add(new PCEPRequestedPathBandwidthObject(new Bandwidth(22.0), true, false));
+       objects.add(new PCEPEndPointsObject<IPv4Address>(IPv4.FAMILY.addressForBytes(new byte[]{1,1,1,1}),
+                       IPv4.FAMILY.addressForBytes(new byte[]{1,1,1,2})));
+               objects.add(new PCEPP2MPEndPointsObject<IPv4Address>(0, IPv4.FAMILY.addressForBytes(new byte[] { 1, 1, 1, 1 }),
+                               Lists.newArrayList(IPv4.FAMILY.addressForBytes(new byte[] { 1, 1, 1, 1 })), true, false));
+
+       for (final PCEPObject o: objects) {
+                       assertThat(o.toString(), containsString("processed=true"));
+                       assertThat(o.toString(), containsString("ignored=false"));
+                       if(o instanceof PCEPBandwidthObject)
+                               assertThat(o.toString(), containsString("bandwidth=Bandwidth [bytesPerSecond=22.0]"));
+                       if(o instanceof PCEPEndPoints)
+                               assertThat(o.toString(), containsString("sourceAddress=1.1.1.1"));
+                       if(o instanceof PCEPP2MPEndPointsObject)
+                               assertThat(o.toString(), containsString("destinationAddresses=[1.1.1.1]"));
+               }
+    }
+
+}
diff --git a/pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/TlvsTest.java b/pcep/api/src/test/java/org/opendaylight/protocol/pcep/api/TlvsTest.java
new file mode 100644 (file)
index 0000000..a3c4356
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.api;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.concepts.IPv4ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.IPv6ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.tlv.IPv4LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.IPv6LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPCleanupTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPSymbolicNameTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPUpdateErrorTlv;
+import org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import org.opendaylight.protocol.pcep.tlv.OFListTlv;
+import org.opendaylight.protocol.pcep.tlv.OverloadedDurationTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+import org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv;
+import org.opendaylight.protocol.pcep.tlv.ReqMissingTlv;
+
+/**
+ *
+ */
+public class TlvsTest {
+       @Test
+       public void IPv4LSPIdentifiersTlvTest() {
+               final IPv4LSPIdentifiersTlv m = new IPv4LSPIdentifiersTlv(new IPv4Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(
+                               new byte[] { (byte) 127, (byte) 0 }), new IPv4ExtendedTunnelIdentifier(new IPv4Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 })));
+               final IPv4LSPIdentifiersTlv m2 = new IPv4LSPIdentifiersTlv(new IPv4Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(
+                               new byte[] { (byte) 127, (byte) 0 }), new IPv4ExtendedTunnelIdentifier(new IPv4Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 })));
+               final IPv4LSPIdentifiersTlv m3 = new IPv4LSPIdentifiersTlv(new IPv4Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(
+                               new byte[] { (byte) 127, (byte) 0 }), new IPv4ExtendedTunnelIdentifier(new IPv4Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 3 })));
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getExtendedTunnelID(), m2.getExtendedTunnelID());
+               assertEquals(m.getLspID(), m2.getLspID());
+               assertEquals(m.getSenderAddress(), m2.getSenderAddress());
+               assertEquals(m.getTunnelID(), m2.getTunnelID());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void IPv6LSPIdentifiersTlvTest() {
+               final IPv6LSPIdentifiersTlv m = new IPv6LSPIdentifiersTlv(new IPv6Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+                                               (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(new byte[] {
+                               (byte) 127, (byte) 0 }), new IPv6ExtendedTunnelIdentifier(new IPv6Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+                                               (byte) 127, (byte) 0, (byte) 0, (byte) 2 })));
+               final IPv6LSPIdentifiersTlv m2 = new IPv6LSPIdentifiersTlv(new IPv6Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+                                               (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(new byte[] {
+                               (byte) 127, (byte) 0 }), new IPv6ExtendedTunnelIdentifier(new IPv6Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+                                               (byte) 127, (byte) 0, (byte) 0, (byte) 2 })));
+               final IPv6LSPIdentifiersTlv m3 = new IPv6LSPIdentifiersTlv(new IPv6Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+                                               (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(new byte[] {
+                               (byte) 127, (byte) 0 }), new IPv6ExtendedTunnelIdentifier(new IPv6Address(
+                               new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+                                               (byte) 127, (byte) 0, (byte) 0, (byte) 3 })));
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getExtendedTunnelID(), m2.getExtendedTunnelID());
+               assertEquals(m.getLspID(), m2.getLspID());
+               assertEquals(m.getSenderAddress(), m2.getSenderAddress());
+               assertEquals(m.getTunnelID(), m2.getTunnelID());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void LSPStateDBVersionTlvTest() {
+               final LSPStateDBVersionTlv m = new LSPStateDBVersionTlv(25);
+               final LSPStateDBVersionTlv m2 = new LSPStateDBVersionTlv(25);
+               final LSPStateDBVersionTlv m3 = new LSPStateDBVersionTlv(26);
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getDbVersion(), m2.getDbVersion());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void LSPSymbolicNameTlvTest() {
+               final LSPSymbolicNameTlv m = new LSPSymbolicNameTlv(new LSPSymbolicName(new byte[] { (byte) 2 }));
+               final LSPSymbolicNameTlv m2 = new LSPSymbolicNameTlv(new LSPSymbolicName(new byte[] { (byte) 2 }));
+               final LSPSymbolicNameTlv m3 = new LSPSymbolicNameTlv(new LSPSymbolicName(new byte[] { (byte) 3 }));
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getSymbolicName(), m2.getSymbolicName());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void LSPUpdateErrorTlvTest() {
+               final LSPUpdateErrorTlv m = new LSPUpdateErrorTlv(new byte[] { (byte) 2, (byte) 2, (byte) 2, (byte) 2 });
+               final LSPUpdateErrorTlv m2 = new LSPUpdateErrorTlv(new byte[] { (byte) 2, (byte) 2, (byte) 2, (byte) 2 });
+               final LSPUpdateErrorTlv m3 = new LSPUpdateErrorTlv(new byte[] { (byte) 2, (byte) 2, (byte) 2, (byte) 3 });
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertArrayEquals(m.getErrorCode(), m2.getErrorCode());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void NoPathVectorTlvTest() {
+               final NoPathVectorTlv m = new NoPathVectorTlv(false, true, false, false, false, false);
+               final NoPathVectorTlv m2 = new NoPathVectorTlv(false, true, false, false, false, false);
+               final NoPathVectorTlv m3 = new NoPathVectorTlv(false, true, true, false, false, false);
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertFalse(m.isPceUnavailable());
+               assertTrue(m.isUnknownDest());
+               assertFalse(m.isUnknownSrc());
+               assertFalse(m.isNoGCOSolution());
+               assertFalse(m.isNoGCOMigrationPath());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void NodeIdentifierTlvTest() throws UnsupportedEncodingException {
+               final NodeIdentifierTlv m = new NodeIdentifierTlv(new byte[] { (byte) 2 });
+               final NodeIdentifierTlv m2 = new NodeIdentifierTlv(new byte[] { (byte) 2 });
+               final NodeIdentifierTlv m3 = new NodeIdentifierTlv(new byte[] { (byte) 79, (byte) 102, (byte) 45, (byte) 57, (byte) 107, (byte) 45, (byte) 48,
+                               (byte) 50 });
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertArrayEquals(m.getValue(), m2.getValue());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+               assertEquals(m3.toString(), "NodeIdentifierTlv [value=Of-9k-02]");
+
+               //non-ascii string
+               final String str = "þščťžéíá";
+
+               //test utf-8 validity
+               assertEquals("NodeIdentifierTlv [value=" + str + "]", new NodeIdentifierTlv(str.getBytes("UTF-8")).toString());
+
+               //test enother encoding, should be represented as raw binary
+               assertEquals("NodeIdentifierTlv [value=" + Arrays.toString(str.getBytes("ISO8859_1")) + "]",
+                               new NodeIdentifierTlv(str.getBytes("ISO8859_1")).toString());
+       }
+
+       @Test
+       public void OverloadedDurationTlvTest() {
+               final OverloadedDurationTlv m = new OverloadedDurationTlv(2);
+               final OverloadedDurationTlv m2 = new OverloadedDurationTlv(2);
+               final OverloadedDurationTlv m3 = new OverloadedDurationTlv(3);
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getValue(), m2.getValue());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void PCEStatefulCapabilityTlvTest() {
+               final PCEStatefulCapabilityTlv m = new PCEStatefulCapabilityTlv(false, true, false);
+               final PCEStatefulCapabilityTlv m2 = new PCEStatefulCapabilityTlv(false, true, false);
+               final PCEStatefulCapabilityTlv m3 = new PCEStatefulCapabilityTlv(true, true, true);
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void RSVPErrorSpecTlvTest() {
+               final RSVPErrorSpecTlv<IPv4Address> m = new RSVPErrorSpecTlv<IPv4Address>(new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), true, true, 2, 2);
+               final RSVPErrorSpecTlv<IPv4Address> m2 = new RSVPErrorSpecTlv<IPv4Address>(new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), true, true, 2, 2);
+               final RSVPErrorSpecTlv<IPv4Address> m3 = new RSVPErrorSpecTlv<IPv4Address>(new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), false, true, 2, 2);
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getErrorCode(), m2.getErrorCode());
+               assertEquals(m.getErrorNodeAddress(), m2.getErrorNodeAddress());
+               assertEquals(m.getErrorValue(), m2.getErrorValue());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void ReqMissingTlvTest() {
+               final ReqMissingTlv m = new ReqMissingTlv(2);
+               final ReqMissingTlv m2 = new ReqMissingTlv(2);
+               final ReqMissingTlv m3 = new ReqMissingTlv(3);
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getRequestID(), m2.getRequestID());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void OFListTlvTest() {
+               final List<PCEPOFCodes> ofcodes = new ArrayList<PCEPOFCodes>();
+
+               final OFListTlv m = new OFListTlv(ofcodes);
+               final OFListTlv m2 = new OFListTlv(ofcodes);
+               final OFListTlv m3 = new OFListTlv(null);
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getOfCodes(), m2.getOfCodes());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+       }
+
+       @Test
+       public void LSPCleanupTlvTest() {
+               final LSPCleanupTlv m = new LSPCleanupTlv(Integer.MAX_VALUE);
+               final LSPCleanupTlv m2 = new LSPCleanupTlv(Integer.MAX_VALUE);
+               final LSPCleanupTlv m3 = new LSPCleanupTlv(0);
+
+               assertEquals(m, m2);
+               assertEquals(m.toString(), m2.toString());
+               assertEquals(m.hashCode(), m2.hashCode());
+               assertEquals(m.getTimeout(), m2.getTimeout());
+               assertFalse(m.equals(null));
+               assertFalse(m.equals(m3));
+               assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+               assertTrue(m.equals(m));
+
+               try {
+                       new LSPCleanupTlv(Integer.MIN_VALUE);
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Timeout (" + Integer.MIN_VALUE + ") cannot be negative or bigger than 2^31 -1.", e.getMessage());
+               }
+       }
+}
diff --git a/pcep/api/src/test/resources/.gitignore b/pcep/api/src/test/resources/.gitignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/pcep/impl/.gitignore b/pcep/impl/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/pcep/impl/.project b/pcep/impl/.project
new file mode 100644 (file)
index 0000000..32158cf
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>pcep-impl</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/pcep/impl/pom.xml b/pcep/impl/pom.xml
new file mode 100644 (file)
index 0000000..f57e639
--- /dev/null
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>pcep-parent</artifactId>
+               <version>1.0</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>pcep-impl</artifactId>
+       <description>PCE Protocol Implementation</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>pcep-api</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>framework</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>util</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.guava</groupId>
+                       <artifactId>guava</artifactId>
+                       <version>${guava.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-api</artifactId>
+                       <version>${slf4j.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>mockito-configuration</artifactId>
+                       <version>1.0</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>framework</artifactId>
+                       <version>1.0</version>
+                       <scope>test</scope>
+                       <type>test-jar</type>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Import-Package>
+                                                       org.opendaylight.protocol.concepts,
+                                                       org.opendaylight.protocol.framework,
+                                                       org.opendaylight.protocol.concepts,
+                                                       com.google.common.base,
+                                                       com.google.common.collect,
+                                                       com.google.common.primitives,
+                                                       javax.annotation,
+                                                       javax.management,
+                            javax.net.ssl,
+                                                       org.opendaylight.protocol.pcep,
+                                                       org.opendaylight.protocol.pcep.concepts,
+                                                       org.opendaylight.protocol.pcep.message,
+                                                       org.opendaylight.protocol.pcep.object,
+                                                       org.opendaylight.protocol.pcep.subobject,
+                                                       org.opendaylight.protocol.pcep.tlv,
+                            org.opendaylight.protocol.util,
+                                                       org.slf4j,
+                                               </Import-Package>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.pcep.impl.*,
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-jar-plugin</artifactId>
+                               <version>2.4</version>
+                               <executions>
+                                       <execution>
+                                               <phase>package</phase>
+                                               <goals>
+                                                       <goal>test-jar</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>PCEP-IMPL Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+
+</project>
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPConnectionImpl.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPConnectionImpl.java
new file mode 100644 (file)
index 0000000..0cf279d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+
+public class PCEPConnectionImpl implements PCEPConnection {
+
+       private final InetSocketAddress address;
+
+       private final PCEPSessionListener listener;
+
+       private final PCEPSessionPreferences proposal;
+
+       private final PCEPSessionProposalChecker checker;
+
+       public PCEPConnectionImpl(final InetSocketAddress address, final PCEPSessionListener listener, final PCEPSessionPreferences proposal,
+                       final PCEPSessionProposalChecker checker) {
+               this.address = address;
+               this.listener = listener;
+               this.proposal = proposal;
+               this.checker = checker;
+       }
+
+       @Override
+       public InetSocketAddress getPeerAddress() {
+               return this.address;
+       }
+
+       @Override
+       public PCEPSessionListener getListener() {
+               return this.listener;
+       }
+
+       @Override
+       public PCEPSessionPreferences getProposal() {
+               return this.proposal;
+       }
+
+       @Override
+       public PCEPSessionProposalChecker getProposalChecker() {
+               return this.checker;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPDispatcherImpl.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPDispatcherImpl.java
new file mode 100644 (file)
index 0000000..7f130bb
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.Dispatcher;
+import org.opendaylight.protocol.framework.ProtocolServer;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPConnectionFactory;
+import org.opendaylight.protocol.pcep.PCEPDispatcher;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
+
+/**
+ * Implementation of PCEPDispatcher.
+ */
+public class PCEPDispatcherImpl implements PCEPDispatcher {
+       public static final int DEFAULT_MAX_UNKNOWN_MSG = 5;
+
+       private int maxUnknownMessages = DEFAULT_MAX_UNKNOWN_MSG;
+
+       private final Dispatcher dispatcher;
+
+       private final PCEPSessionProposalFactory proposalFactory;
+
+       /**
+        * Creates an instance of PCEPDispatcherImpl, gets the default selector and opens it.
+        * 
+        * @throws IOException if some error occurred during opening the selector
+        */
+       public PCEPDispatcherImpl(final Dispatcher dispatcher, final PCEPSessionProposalFactory proposalFactory) {
+               this.dispatcher = dispatcher;
+               this.proposalFactory = proposalFactory;
+       }
+
+       @Override
+       public ProtocolServer createServer(final InetSocketAddress address, final PCEPConnectionFactory connectionFactory) throws IOException {
+               connectionFactory.setProposal(this.proposalFactory, address, 0);
+               return this.dispatcher.createServer(address, connectionFactory, new PCEPSessionFactoryImpl(this.maxUnknownMessages),
+                               PCEPInputStream.FACTORY);
+       }
+
+       /**
+        * Create client is used for mock purposes only.
+        */
+       @Override
+       public PCEPSession createClient(final PCEPConnection connection) throws IOException {
+               return (PCEPSession) this.dispatcher.createClient(connection, new PCEPSessionFactoryImpl(this.maxUnknownMessages),
+                               PCEPInputStream.FACTORY);
+       }
+
+       @Override
+       public void setMaxUnknownMessages(final int limit) {
+               this.maxUnknownMessages = limit;
+       }
+
+       public int getMaxUnknownMessages() {
+               return this.maxUnknownMessages;
+       }
+
+       public Dispatcher getDispatcher() {
+               return this.dispatcher;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPEROSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPEROSubobjectParser.java
new file mode 100644 (file)
index 0000000..350600c
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.subobject.EROAsNumberSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROExplicitExclusionRouteSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROIPv4PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROIPv6PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROLabelSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROPathKeyWith128PCEIDSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROPathKeyWith32PCEIDSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROProtectionSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROUnnumberedInterfaceSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROExplicitExclusionRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.PCEPSubobject PCEPSubobject}
+ */
+public class PCEPEROSubobjectParser {
+
+    private static final Logger logger = LoggerFactory.getLogger(PCEPEROSubobjectParser.class);
+
+    /**
+     * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPSubobject
+     * PCEPSubobject}
+     */
+    public enum PCEPSubobjectType {
+               IPv4_PREFIX(1), IPv6_PREFIX(2), LABEL(3), UNNUMBERED_INTERFACE_ID(4), AS_NUMBER(32), EXRS(33), PROTECTION(37), PK_32(
+                               64), PK_128(65);
+
+               private final int indicator;
+
+               PCEPSubobjectType(int indicator) {
+                       this.indicator = indicator;
+               }
+
+               public int getIndicator() {
+                       return this.indicator;
+               }
+
+               public static PCEPSubobjectType getFromInt(int type) throws PCEPDeserializerException {
+
+                       for (final PCEPSubobjectType type_e : PCEPSubobjectType.values()) {
+                               if (type_e.getIndicator() == type)
+                                       return type_e;
+                       }
+
+                       throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + "; Known: "
+                                       + PCEPSubobjectType.values() + ".");
+               }
+       }
+
+    /*
+     * Fields lengths in Bytes
+     */
+    public static final int TYPE_FLAG_F_LENGTH = 1;
+    public static final int LENGTH_F_LENGTH = 1;
+
+    /*
+     * Fields offsets in Bytes
+     */
+    public static final int TYPE_FLAG_F_OFFSET = 0;
+    public static final int LENGTH_F_OFFSET = TYPE_FLAG_F_OFFSET + TYPE_FLAG_F_LENGTH;
+    public static final int SO_CONTENTS_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
+
+    public static List<ExplicitRouteSubobject> parse(byte[] bytes) throws PCEPDeserializerException {
+       if (bytes == null)
+           throw new IllegalArgumentException("Byte array is mandatory.");
+
+       final List<ExplicitRouteSubobject> subobjsList = new ArrayList<ExplicitRouteSubobject>();
+       boolean loose_flag;
+       PCEPSubobjectType type;
+       byte[] soContentsBytes;
+       int length;
+       int offset = 0;
+
+       while (offset < bytes.length) {
+
+           loose_flag = ((bytes[offset + TYPE_FLAG_F_OFFSET] & (1 << 7)) != 0) ? true : false;
+           length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
+
+           type = PCEPSubobjectType.getFromInt((bytes[offset + TYPE_FLAG_F_OFFSET] & 0xff) & ~(1 << 7));
+
+           if (length > bytes.length - offset)
+               throw new PCEPDeserializerException("Wrong length specified. Passed: " + length + "; Expected: <= " + (bytes.length - offset));
+
+           soContentsBytes = new byte[length - SO_CONTENTS_OFFSET];
+           System.arraycopy(bytes, offset + SO_CONTENTS_OFFSET, soContentsBytes, 0, length - SO_CONTENTS_OFFSET);
+
+           logger.debug("Attempt to parse subobject from bytes: {}", ByteArray.bytesToHexString(soContentsBytes));
+           final ExplicitRouteSubobject subObj = parseSpecificSubobject(type, soContentsBytes, loose_flag);
+           logger.debug("Subobject was parsed. {}", subObj);
+
+           subobjsList.add(subObj);
+
+           offset += length;
+       }
+
+       return subobjsList;
+    }
+
+    public static byte[] put(List<ExplicitRouteSubobject> objsToSerialize) {
+       final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
+
+       int length = 0;
+       for (final ExplicitRouteSubobject obj : objsToSerialize) {
+           final byte[] bytes = put(obj);
+           length += bytes.length;
+           bytesList.add(bytes);
+       }
+
+       final byte[] retBytes = new byte[length];
+
+       int offset = 0;
+       for (final byte[] bytes : bytesList) {
+           System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
+           offset += bytes.length;
+       }
+
+       return retBytes;
+    }
+
+    public static byte[] put(ExplicitRouteSubobject objToSerialize) {
+       int typeIndicator = 0;
+
+       final byte[] soContentsBytes;
+
+       if (objToSerialize instanceof EROIPPrefixSubobject<?> && ((EROIPPrefixSubobject<?>) objToSerialize).getPrefix() instanceof IPv4Prefix) {
+           typeIndicator = PCEPSubobjectType.IPv4_PREFIX.getIndicator();
+           soContentsBytes = EROIPv4PrefixSubobjectParser.put(objToSerialize);
+       } else if (objToSerialize instanceof EROIPPrefixSubobject<?> && ((EROIPPrefixSubobject<?>) objToSerialize).getPrefix() instanceof IPv6Prefix) {
+           typeIndicator = PCEPSubobjectType.IPv6_PREFIX.getIndicator();
+           soContentsBytes = EROIPv6PrefixSubobjectParser.put(objToSerialize);
+       } else if (objToSerialize instanceof EROAsNumberSubobject) {
+           typeIndicator = PCEPSubobjectType.AS_NUMBER.getIndicator();
+           soContentsBytes = EROAsNumberSubobjectParser.put(objToSerialize);
+       } else if (objToSerialize instanceof EROUnnumberedInterfaceSubobject) {
+           typeIndicator = PCEPSubobjectType.UNNUMBERED_INTERFACE_ID.getIndicator();
+           soContentsBytes = EROUnnumberedInterfaceSubobjectParser.put(objToSerialize);
+       } else if (objToSerialize instanceof EROLabelSubobject) {
+           typeIndicator = PCEPSubobjectType.LABEL.getIndicator();
+           soContentsBytes = EROLabelSubobjectParser.put((EROLabelSubobject) objToSerialize);
+       } else if (objToSerialize instanceof EROExplicitExclusionRouteSubobject) {
+           typeIndicator = PCEPSubobjectType.EXRS.getIndicator();
+           soContentsBytes = EROExplicitExclusionRouteSubobjectParser.put((EROExplicitExclusionRouteSubobject) objToSerialize);
+       } else if (objToSerialize instanceof EROPathKeyWith32PCEIDSubobject) {
+           typeIndicator = PCEPSubobjectType.PK_32.getIndicator();
+           soContentsBytes = EROPathKeyWith32PCEIDSubobjectParser.put((EROPathKeyWith32PCEIDSubobject) objToSerialize);
+       } else if (objToSerialize instanceof EROPathKeyWith128PCEIDSubobject) {
+           typeIndicator = PCEPSubobjectType.PK_128.getIndicator();
+           soContentsBytes = EROPathKeyWith128PCEIDSubobjectParser.put((EROPathKeyWith128PCEIDSubobject) objToSerialize);
+       } else if (objToSerialize instanceof EROProtectionSubobject) {
+           typeIndicator = PCEPSubobjectType.PROTECTION.getIndicator();
+           soContentsBytes = EROProtectionSubobjectParser.put((EROProtectionSubobject) objToSerialize);
+       } else
+           throw new IllegalArgumentException("Unknown instance of PCEPSubobject. Passed: " + objToSerialize.getClass() + ".");
+
+       final byte[] bytes = new byte[SO_CONTENTS_OFFSET + soContentsBytes.length];
+
+       bytes[TYPE_FLAG_F_OFFSET] = (byte) (ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_FLAG_F_LENGTH)[0] | (objToSerialize
+               .isLoose() ? 1 << 7 : 0));
+       bytes[LENGTH_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(soContentsBytes.length + SO_CONTENTS_OFFSET), (Integer.SIZE / 8) - LENGTH_F_LENGTH)[0];
+
+       System.arraycopy(soContentsBytes, 0, bytes, SO_CONTENTS_OFFSET, soContentsBytes.length);
+
+       return bytes;
+    }
+
+    private static ExplicitRouteSubobject parseSpecificSubobject(PCEPSubobjectType type, byte[] soContentsBytes, boolean loose_flag)
+           throws PCEPDeserializerException {
+
+       switch (type) {
+           case IPv4_PREFIX:
+               return EROIPv4PrefixSubobjectParser.parse(soContentsBytes, loose_flag);
+           case IPv6_PREFIX:
+               return EROIPv6PrefixSubobjectParser.parse(soContentsBytes, loose_flag);
+           case UNNUMBERED_INTERFACE_ID:
+               return EROUnnumberedInterfaceSubobjectParser.parse(soContentsBytes, loose_flag);
+           case AS_NUMBER:
+               return EROAsNumberSubobjectParser.parse(soContentsBytes, loose_flag);
+           case LABEL:
+               return EROLabelSubobjectParser.parse(soContentsBytes, loose_flag);
+           case EXRS:
+               return EROExplicitExclusionRouteSubobjectParser.parse(soContentsBytes, loose_flag);
+           case PK_32:
+               return EROPathKeyWith32PCEIDSubobjectParser.parse(soContentsBytes, loose_flag);
+           case PK_128:
+               return EROPathKeyWith128PCEIDSubobjectParser.parse(soContentsBytes, loose_flag);
+           case PROTECTION:
+               return EROProtectionSubobjectParser.parse(soContentsBytes, loose_flag);
+           default:
+               throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + ".");
+       }
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPInputStream.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPInputStream.java
new file mode 100644 (file)
index 0000000..0cb56d7
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolInputStream;
+import org.opendaylight.protocol.framework.ProtocolInputStreamFactory;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+
+/**
+ *
+ */
+public class PCEPInputStream implements ProtocolInputStream {
+       static final ProtocolInputStreamFactory FACTORY = new ProtocolInputStreamFactory() {
+               @Override
+               public ProtocolInputStream getProtocolInputStream(final PipedInputStream pis, final ProtocolMessageFactory pmf) {
+                       return new PCEPInputStream(pis, pmf);
+               }
+       };
+
+       private final ProtocolMessageFactory factory;
+       private final PipedInputStream inputStream;
+       private PCEPMessageHeader header;
+
+       public PCEPInputStream(final PipedInputStream inputStream, final ProtocolMessageFactory factory) {
+               this.factory = factory;
+               this.inputStream = inputStream;
+               this.header = new PCEPMessageHeader();
+       }
+
+       /**
+        * Check availability of a message in underlying input stream. A message is available when there are more or the
+        * same amount of bytes in the stream as the message length is specified in message header. If there are not enough
+        * bytes for the message or even to read a message header, return false.
+        *
+        * @return true if there are enough bytes to read a message false if there are not enough bytes to read a message or
+        *         a message header.
+        * @throws IOException
+        */
+       @Override
+       public synchronized boolean isMessageAvailable() throws IOException {
+               if (!this.header.isParsed()) {
+                       // No header, try to parse it
+                       this.header = this.parseHeaderIfAvailable();
+
+                       if (!this.header.isParsed()) {
+                               // No luck, we do not have a message
+                               return false;
+                       }
+               }
+               // message length contains the size of the header too
+               if (this.inputStream.available() < (this.header.getLength() - PCEPMessageHeader.COMMON_HEADER_LENGTH)) {
+                       return false;
+               }
+               return true;
+       }
+
+       /**
+        * If there are enough bytes in the underlying stream, parse the message. Blocking, till there are enough bytes to
+        * read, therefore the call of method isMessageAvailable() is suggested first.
+        *
+        * @param factory protocol specific message factory
+        * @return protocol specific message
+        * @throws DeserializerException
+        * @throws IOException
+        * @throws DocumentedException
+        */
+       @Override
+       public synchronized ProtocolMessage getMessage() throws DeserializerException, IOException, DocumentedException {
+               // isMessageAvailable wasn't called, or there were not enough bytes to form message header
+               // blocking till the header is available
+               while (!this.header.isParsed()) {
+                       this.header = this.parseHeaderIfAvailable();
+               }
+               final byte[] bytes = new byte[this.header.getLength() - PCEPMessageHeader.COMMON_HEADER_LENGTH]; // message
+                                                                                                                                                                                                                       // length
+                                                                                                                                                                                                                       // contains
+                                                                                                                                                                                                                       // the size
+                                                                                                                                                                                                                       // of the
+                                                                                                                                                                                                                       // header
+                                                                                                                                                                                                                       // too
+               // blocking till the whole message is available
+               if (this.inputStream.read(bytes) == -1) {
+                       throw new IOException("PipedInputStream was closed, before data could be read from it.");
+               }
+               final ProtocolMessage msg = this.factory.parse(bytes, this.header);
+
+               this.header.setParsed(); // if we have all the bytes to send the message for parsing, clear the header, to let know,
+                                                               // we're ready to read another message
+
+               return msg;
+       }
+
+       /**
+        * Checks if there are enough bytes to parse a header and parses it. Non-blocking: if there are not enough bytes to
+        * parse a message header, returns false.
+        *
+        * @return cleared header if no header is available
+        * @return header object when enough data is available
+        */
+       private PCEPMessageHeader parseHeaderIfAvailable() throws IOException {
+               if (this.inputStream.available() < PCEPMessageHeader.COMMON_HEADER_LENGTH) {
+                       this.header.setParsed();
+                       return this.header;
+               }
+
+               final byte[] messageHeader = new byte[PCEPMessageHeader.COMMON_HEADER_LENGTH];
+               if (this.inputStream.read(messageHeader) == -1) {
+                       this.header.setParsed();
+                       return this.header;
+               }
+               return this.header.fromBytes(messageHeader);
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageFactory.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageFactory.java
new file mode 100644 (file)
index 0000000..f77b970
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.HashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.message.PCCreateMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPCloseMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPErrorMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPKeepAliveMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPNotificationMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPOpenMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPRawMessage;
+import org.opendaylight.protocol.pcep.impl.message.PCEPReplyMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPReportMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPRequestMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPUpdateRequestMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPXRAddTunnelMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPXRDeleteTunnelMessageParser;
+import org.opendaylight.protocol.pcep.message.PCCreateMessage;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
+import org.opendaylight.protocol.pcep.message.PCEPXRAddTunnelMessage;
+import org.opendaylight.protocol.pcep.message.PCEPXRDeleteTunnelMessage;
+
+/**
+ * Factory for subclasses of {@link org.opendaylight.protocol.pcep.PCEPMessage PCEPMessage}
+ */
+public class PCEPMessageFactory implements ProtocolMessageFactory {
+
+    private final static Logger logger = LoggerFactory.getLogger(PCEPMessageFactory.class);
+
+    /**
+     * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPMessage PCEPMessage}
+     */
+    public enum PCEPMessageType {
+               OPEN(1), NOTIFICATION(5), KEEPALIVE(2), RESPONSE(4), REQUEST(3), ERROR(6), CLOSE(7), UPDATE_REQUEST(11), STATUS_REPORT(10),
+               // TODO: replace with actual values by IANA
+               XR_ADD_TUNNEL(8),
+               XR_DELETE_TUNNEL(9),
+               PCCREATE(12);
+
+               private final int identifier;
+
+               PCEPMessageType(final int identifier) {
+                   this.identifier = identifier;
+               }
+
+               public int getIdentifier() {
+                   return this.identifier;
+               }
+
+               public static PCEPMessageType getFromInt(final int type) throws PCEPDeserializerException {
+
+                   for (final PCEPMessageType type_e : PCEPMessageType.values()) {
+                       if (type_e.getIdentifier() == type)
+                           return type_e;
+                   }
+
+                   throw new PCEPDeserializerException("Unknown PCEPMessage Class identifier. Passed: " + type + "; Known: " + PCEPMessageType.values() + ".");
+               }
+       }
+
+    private static class MapOfParsers extends HashMap<PCEPMessageType, PCEPMessageParser> {
+
+       private static final long serialVersionUID = -5715193806554448822L;
+
+       private final static MapOfParsers instance = new MapOfParsers();
+
+       private MapOfParsers() {
+           this.fillInMap();
+       }
+
+       private void fillInMap() {
+           this.put(PCEPMessageType.OPEN, new PCEPOpenMessageParser());
+           this.put(PCEPMessageType.KEEPALIVE, new PCEPKeepAliveMessageParser());
+           this.put(PCEPMessageType.NOTIFICATION, new PCEPNotificationMessageParser());
+           this.put(PCEPMessageType.ERROR, new PCEPErrorMessageParser());
+           this.put(PCEPMessageType.RESPONSE, new PCEPReplyMessageParser());
+           this.put(PCEPMessageType.REQUEST, new PCEPRequestMessageParser());
+           this.put(PCEPMessageType.UPDATE_REQUEST, new PCEPUpdateRequestMessageParser());
+           this.put(PCEPMessageType.STATUS_REPORT, new PCEPReportMessageParser());
+           this.put(PCEPMessageType.CLOSE, new PCEPCloseMessageParser());
+           this.put(PCEPMessageType.XR_ADD_TUNNEL, new PCEPXRAddTunnelMessageParser());
+           this.put(PCEPMessageType.XR_DELETE_TUNNEL, new PCEPXRDeleteTunnelMessageParser());
+           this.put(PCEPMessageType.PCCREATE, new PCCreateMessageParser());
+       }
+
+       public static MapOfParsers getInstance() {
+           return instance;
+               }
+    }
+
+    /**
+     *
+     * @param bytes
+     *            assume array of bytes without common header
+     * @param msgHeader
+     * @return Parsed specific PCEPMessage
+     * @throws PCEPDeserializerException
+     * @throws PCEPDocumentedException
+     */
+
+    @Override
+       public ProtocolMessage parse(final byte[] bytes, final ProtocolMessageHeader msgH) throws DeserializerException, DocumentedException {
+       final PCEPMessageHeader msgHeader = (PCEPMessageHeader) msgH;
+               if (bytes == null)
+                   throw new IllegalArgumentException("Array of bytes is mandatory.");
+               if (msgHeader == null)
+                   throw new IllegalArgumentException("PCEPMessageHeader is mandatory.");
+
+               logger.trace("Attempt to parse message from bytes: {}", ByteArray.bytesToHexString(bytes));
+
+               if (bytes.length != (msgHeader.getLength() - PCEPMessageHeader.COMMON_HEADER_LENGTH))
+                   throw new DeserializerException("Size don't match size specified in header. Passed: " + bytes.length + "; Expected: "
+                           + (msgHeader.getLength() - PCEPMessageHeader.COMMON_HEADER_LENGTH) + ". " + msgHeader.getLength());
+
+               /*
+                * if PCEPObjectIdentifier.getObjectClassFromInt() dont't throws
+                * exception and if returned null we know the error type
+                */
+               PCEPMessageType msgType;
+               try {
+                       msgType = PCEPMessageType.getFromInt(msgHeader.getType());
+               } catch (final PCEPDeserializerException e) {
+                       throw new DeserializerException(e.getMessage(), e);
+               }
+               if (msgType == null)
+                   throw new DocumentedException("Unhandled message type " + msgHeader.getType(), new PCEPDocumentedException("Unhandled message type " + msgHeader.getType(), PCEPErrors.CAPABILITY_NOT_SUPPORTED));
+
+               PCEPMessage msg;
+               try {
+                       msg = new PCEPRawMessage(PCEPObjectFactory.parseObjects(bytes), msgType);
+               } catch (final PCEPDeserializerException e) {
+                       throw new DeserializerException(e.getMessage(), e);
+               } catch (final PCEPDocumentedException e) {
+                       throw new DocumentedException(e.getMessage(), e);
+               }
+               logger.debug("Message was parsed. {}", msg);
+               return msg;
+    }
+
+    @Override
+       public byte[] put(final ProtocolMessage msg) {
+       final PCEPMessage pcepMsg = (PCEPMessage) msg;
+               if (pcepMsg == null)
+                   throw new IllegalArgumentException("PCEPMessage is mandatory.");
+
+               final PCEPMessageType msgType;
+
+               if (pcepMsg instanceof PCEPOpenMessage) {
+                   msgType = PCEPMessageType.OPEN;
+               } else if (pcepMsg instanceof PCEPKeepAliveMessage) {
+                   msgType = PCEPMessageType.KEEPALIVE;
+               } else if (pcepMsg instanceof PCEPCloseMessage) {
+                   msgType = PCEPMessageType.CLOSE;
+               } else if (pcepMsg instanceof PCEPReplyMessage) {
+                   msgType = PCEPMessageType.RESPONSE;
+               } else if (pcepMsg instanceof PCEPRequestMessage) {
+                   msgType = PCEPMessageType.REQUEST;
+               } else if (pcepMsg instanceof PCEPNotificationMessage) {
+                   msgType = PCEPMessageType.NOTIFICATION;
+               } else if (pcepMsg instanceof PCEPErrorMessage) {
+                   msgType = PCEPMessageType.ERROR;
+               } else if (pcepMsg instanceof PCEPReportMessage) {
+                   msgType = PCEPMessageType.STATUS_REPORT;
+               } else if (pcepMsg instanceof PCEPUpdateRequestMessage) {
+                   msgType = PCEPMessageType.UPDATE_REQUEST;
+               } else if (pcepMsg instanceof PCEPXRAddTunnelMessage) {
+                   msgType = PCEPMessageType.XR_ADD_TUNNEL;
+               } else if (pcepMsg instanceof PCEPXRDeleteTunnelMessage) {
+                   msgType = PCEPMessageType.XR_DELETE_TUNNEL;
+               } else if (pcepMsg instanceof PCCreateMessage) {
+                   msgType = PCEPMessageType.PCCREATE;
+               } else {
+                   logger.error("Unknown instance of PCEPMessage. Message class: {}", pcepMsg.getClass());
+                   throw new IllegalArgumentException("Unknown instance of PCEPMessage. Passed " + pcepMsg.getClass());
+               }
+
+               logger.trace("Serializing {}", msgType);
+
+               final byte[] msgBody = MapOfParsers.getInstance().get(msgType).put(pcepMsg);
+
+               final PCEPMessageHeader msgHeader = new PCEPMessageHeader(msgType.getIdentifier(), msgBody.length + PCEPMessageHeader.COMMON_HEADER_LENGTH,
+                               PCEPMessage.PCEP_VERSION);
+
+               final byte[] headerBytes = msgHeader.toBytes();
+               final byte[] retBytes = new byte[headerBytes.length + msgBody.length];
+
+               ByteArray.copyWhole(headerBytes, retBytes, 0);
+               ByteArray.copyWhole(msgBody, retBytes, PCEPMessageHeader.COMMON_HEADER_LENGTH);
+
+               return retBytes;
+    }
+}
+
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageHeader.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageHeader.java
new file mode 100644 (file)
index 0000000..6cdf638
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Header parser for {@link org.opendaylight.protocol.pcep.PCEPMessage PCEPMessage}
+ */
+public final class PCEPMessageHeader implements ProtocolMessageHeader {
+
+       public static final Logger logger = LoggerFactory.getLogger(PCEPMessageHeader.class);
+
+       /*
+        * lengths of fields in bytes
+        */
+       private static final int VER_FLAGS_MF_LENGTH = 1;
+       private static final int TYPE_F_LENGTH = 1;
+       private static final int LENGTH_F_LENGTH = 2;
+
+       /*
+        * lengths of subfields inside multi-field in bits
+        */
+       private static final int VERSION_SF_LENGTH = 3;
+
+       /*
+        * offsets of field in bytes
+        */
+       private static final int VER_FLAGS_MF_OFFSET = 0;
+       private static final int TYPE_F_OFFSET = VER_FLAGS_MF_LENGTH + VER_FLAGS_MF_OFFSET;
+       private static final int LENGTH_F_OFFSET = TYPE_F_LENGTH + TYPE_F_OFFSET;
+
+       /*
+        * offsets of subfields inside multi-filed in bits
+        */
+
+       private static final int VERSION_SF_OFFSET = 0;
+
+       /*
+        * COMMON HEADER LENGTH
+        */
+       public static final int COMMON_HEADER_LENGTH = VER_FLAGS_MF_LENGTH + TYPE_F_LENGTH + LENGTH_F_LENGTH;
+
+       private int type;
+       private int length;
+       private int version;
+
+       private boolean parsed = false;
+
+       public PCEPMessageHeader() {
+
+       }
+
+       public PCEPMessageHeader(final int type, final int length, final int version) {
+               this.type = type;
+               this.length = length;
+               this.version = version;
+       }
+
+       public PCEPMessageHeader fromBytes(final byte[] bytes) {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Array of bytes is mandatory");
+
+               logger.trace("Attempt to parse message header: {}", ByteArray.bytesToHexString(bytes));
+
+               if (bytes.length < COMMON_HEADER_LENGTH)
+                       throw new IllegalArgumentException("Too few bytes in passed array. Passed: " + bytes.length + "; Expected: >= " + COMMON_HEADER_LENGTH + ".");
+
+               this.type = UnsignedBytes.toInt(bytes[TYPE_F_OFFSET]);
+
+               this.length = ByteArray.bytesToInt(Arrays.copyOfRange(bytes,
+                               LENGTH_F_OFFSET, LENGTH_F_OFFSET + LENGTH_F_LENGTH));
+
+               this.version = ByteArray.copyBitsRange(bytes[VER_FLAGS_MF_OFFSET], VERSION_SF_OFFSET, VERSION_SF_LENGTH);
+
+               logger.trace("Message header was parsed. {}", this);
+               this.parsed = true;
+               return this;
+       }
+
+       public byte[] toBytes() {
+               final byte[] retBytes = new byte[COMMON_HEADER_LENGTH];
+
+               // msgVer_Flag
+               retBytes[VER_FLAGS_MF_OFFSET] = (byte) (this.version << (Byte.SIZE - VERSION_SF_LENGTH));
+
+               // msgType
+               retBytes[TYPE_F_OFFSET] = (byte) this.type;
+
+               // msgLength
+               System.arraycopy(ByteArray.intToBytes(this.length), Integer.SIZE / Byte.SIZE - LENGTH_F_LENGTH, retBytes, LENGTH_F_OFFSET, LENGTH_F_LENGTH);
+
+               return retBytes;
+       }
+
+       public void setLength(final int length) {
+               this.length = length;
+       }
+
+       public void setType(final int type) {
+               this.type = type;
+       }
+
+       public void setVersion(final int version) {
+               this.version = version;
+       }
+
+       public int getLength() {
+               return this.length;
+       }
+
+       public int getVersion() {
+               return this.version;
+       }
+
+       public int getType() {
+               return this.type;
+       }
+
+       /**
+        * @return the parsed
+        */
+       public boolean isParsed() {
+               return this.parsed;
+       }
+
+       /**
+        * @param parsed the parsed to set
+        */
+       public void setParsed() {
+               this.parsed = false;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPMessageHeader [type=");
+               builder.append(this.type);
+               builder.append(", length=");
+               builder.append(this.length);
+               builder.append(", version=");
+               builder.append(this.version);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageParser.java
new file mode 100644 (file)
index 0000000..b49848e
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+
+/**
+ * Interface for specific message parsers
+ */
+public interface PCEPMessageParser {
+
+       public byte[] put(PCEPMessage obj);
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPMessageValidator.java
new file mode 100644 (file)
index 0000000..31c6686
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageFactory.PCEPMessageType;
+import org.opendaylight.protocol.pcep.impl.message.PCCreateMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPCloseMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPErrorMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPKeepAliveMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPNotificationMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPOpenMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPReplyMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPReportMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPRequestMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPUpdateRequestMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPXRAddTunnelMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPXRDeleteTunnelMessageValidator;
+
+/**
+ * Base class for message validators
+ */
+public abstract class PCEPMessageValidator {
+
+       private static class MapOfValidators extends HashMap<PCEPMessageType, PCEPMessageValidator> {
+
+               private static final long serialVersionUID = -5715193806554448822L;
+
+               private final static MapOfValidators instance = new MapOfValidators();
+
+               private MapOfValidators() {
+                       this.fillInMap();
+               }
+
+               private void fillInMap() {
+                       this.put(PCEPMessageType.OPEN, new PCEPOpenMessageValidator());
+                       this.put(PCEPMessageType.KEEPALIVE, new PCEPKeepAliveMessageValidator());
+                       this.put(PCEPMessageType.NOTIFICATION, new PCEPNotificationMessageValidator());
+                       this.put(PCEPMessageType.ERROR, new PCEPErrorMessageValidator());
+                       this.put(PCEPMessageType.RESPONSE, new PCEPReplyMessageValidator());
+                       this.put(PCEPMessageType.REQUEST, new PCEPRequestMessageValidator());
+                       this.put(PCEPMessageType.UPDATE_REQUEST, new PCEPUpdateRequestMessageValidator());
+                       this.put(PCEPMessageType.STATUS_REPORT, new PCEPReportMessageValidator());
+                       this.put(PCEPMessageType.CLOSE, new PCEPCloseMessageValidator());
+                       this.put(PCEPMessageType.XR_ADD_TUNNEL, new PCEPXRAddTunnelMessageValidator());
+                       this.put(PCEPMessageType.XR_DELETE_TUNNEL, new PCEPXRDeleteTunnelMessageValidator());
+                       this.put(PCEPMessageType.PCCREATE, new PCCreateMessageValidator());
+               }
+
+               public static MapOfValidators getInstance() {
+                       return instance;
+               }
+       }
+
+       public abstract List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException;
+
+       public static PCEPMessageValidator getValidator(final PCEPMessageType msgType) {
+               return MapOfValidators.getInstance().get(msgType);
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPOFCodesMapping.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPOFCodesMapping.java
new file mode 100644 (file)
index 0000000..d93e810
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+
+/**
+ * Mapping of enumerable objective function codes to integral identifiers and
+ * vice-versa.
+ */
+public class PCEPOFCodesMapping {
+       private static final PCEPOFCodesMapping instance = new PCEPOFCodesMapping();
+
+       private final Map<PCEPOFCodes, Integer> ofCodesMap = new EnumMap<PCEPOFCodes, Integer>(PCEPOFCodes.class);
+       private final Map<Integer, PCEPOFCodes> ofCodeIdsMap = new HashMap<Integer, PCEPOFCodes>();
+
+       private PCEPOFCodesMapping() {
+               this.fillIn();
+       }
+
+       private void fillIn() {
+               this.fillIn(1, PCEPOFCodes.MCP);
+               this.fillIn(2, PCEPOFCodes.MLP);
+               this.fillIn(3, PCEPOFCodes.MBP);
+               this.fillIn(4, PCEPOFCodes.MBC);
+               this.fillIn(5, PCEPOFCodes.MLL);
+               this.fillIn(6, PCEPOFCodes.MCC);
+               this.fillIn(7, PCEPOFCodes.SPT);
+               this.fillIn(8, PCEPOFCodes.MCT);
+       }
+
+       private void fillIn(int identifier, PCEPOFCodes ofCode) {
+               this.ofCodesMap.put(ofCode, identifier);
+               this.ofCodeIdsMap.put(identifier, ofCode);
+       }
+
+       public int getFromOFCodesEnum(PCEPOFCodes ofCode) {
+               final Integer ofci = this.ofCodesMap.get(ofCode);
+               if (ofci == null)
+                       throw new NoSuchElementException("Unknown PCEPOFCodes type: " + ofCode);
+               return ofci;
+       }
+
+       public PCEPOFCodes getFromCodeIdentifier(int identifier) {
+               final PCEPOFCodes ofc = this.ofCodeIdsMap.get(identifier);
+               if (ofc == null)
+                       throw new NoSuchElementException("Unknown PCEPOFCode identifier.");
+               return ofc;
+       }
+
+       public static PCEPOFCodesMapping getInstance() {
+               return instance;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectFactory.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectFactory.java
new file mode 100644 (file)
index 0000000..6ceecbd
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectIdentifier.ObjectClass;
+import org.opendaylight.protocol.pcep.impl.object.PCEPBranchNodeListObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPCloseObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPEndPointsIPv4ObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPEndPointsIPv6ObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPErrorObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPExcludeRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPExistingPathBandwidthObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPExplicitRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPGlobalConstraintsObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPIncludeRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPLoadBalancingObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPLspObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPLspaObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPMetricObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPNoPathObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPNonBranchNodeListObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPNotificationObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPObjectiveFunctionObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPOpenObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPP2MPEndPointsIPv4ObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPP2MPEndPointsIPv6ObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPReportedRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPRequestParameterObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPRequestedPathBandwidthObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPSecondaryExplicitRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPSecondaryRecordRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPSvecObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPUnreachedIPv4DestinationObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPUnreachedIPv6DestinationObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.object.PCEPBranchNodeListObject;
+import org.opendaylight.protocol.pcep.object.PCEPBranchNodeObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPNonBranchNodeListObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryRecordRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+import org.opendaylight.protocol.pcep.object.PCEPUnreachedDestinationObject;
+
+/**
+ * Factory for subclasses of {@link org.opendaylight.protocol.pcep.PCEPObject PCEPObject}
+ */
+public class PCEPObjectFactory {
+
+    private static final Logger logger = LoggerFactory.getLogger(PCEPObjectFactory.class);
+
+    /**
+     * Map of parsers for subobjects of {@link org.opendaylight.protocol.pcep.PCEPObject
+     * PCEPObject}
+     */
+    private static class MapOfParsers extends HashMap<PCEPObjectIdentifier, PCEPObjectParser> {
+       private static final long serialVersionUID = 1L;
+
+       private final static MapOfParsers instance = new MapOfParsers();
+
+       private MapOfParsers() {
+           this.fillInMap();
+       }
+
+       private void fillInMap() {
+           this.put(new PCEPObjectIdentifier(ObjectClass.OPEN, 1), new PCEPOpenObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.RP, 1), new PCEPRequestParameterObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.NO_PATH, 1), new PCEPNoPathObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.BANDWIDTH, 1), new PCEPRequestedPathBandwidthObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.BANDWIDTH, 2), new PCEPExistingPathBandwidthObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.METRIC, 1), new PCEPMetricObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 1), new PCEPEndPointsIPv4ObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 2), new PCEPEndPointsIPv6ObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.LSPA, 1), new PCEPLspaObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.SVEC, 1), new PCEPSvecObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.NOTIFICATION, 1), new PCEPNotificationObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.ERROR, 1), new PCEPErrorObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.CLOSE, 1), new PCEPCloseObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.LOAD_BALANCING, 1), new PCEPLoadBalancingObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.LSP, 1), new PCEPLspObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.ERO, 1), new PCEPExplicitRouteObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.RRO, 1), new PCEPReportedRouteObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.IRO, 1), new PCEPIncludeRouteObjectParser());
+
+           /* GCO extension */
+           this.put(new PCEPObjectIdentifier(ObjectClass.XRO, 1), new PCEPExcludeRouteObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.OBJCETIVE_FUNCTION, 1), new PCEPObjectiveFunctionObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.GLOBAL_CONSTRAINTS, 1), new PCEPGlobalConstraintsObjectParser());
+
+           /* RFC6006 */
+           this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 3), new PCEPP2MPEndPointsIPv4ObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 4), new PCEPP2MPEndPointsIPv6ObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.UNREACHED_DESTINATION, 1), new PCEPUnreachedIPv4DestinationObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.UNREACHED_DESTINATION, 2), new PCEPUnreachedIPv6DestinationObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.SERO, 1), new PCEPSecondaryExplicitRouteObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.SRRO, 1), new PCEPSecondaryRecordRouteObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.BRANCH_NODE, 1), new PCEPBranchNodeListObjectParser());
+           this.put(new PCEPObjectIdentifier(ObjectClass.BRANCH_NODE, 2), new PCEPNonBranchNodeListObjectParser());
+       }
+
+       public static MapOfParsers getInstance() {
+           return instance;
+       }
+    }
+
+    private static PCEPObject parse(final byte[] bytes, final PCEPObjectHeader header) throws PCEPDocumentedException, PCEPDeserializerException {
+               if (bytes == null)
+                   throw new IllegalArgumentException("Array of bytes is mandatory.");
+               if (header == null)
+                   throw new IllegalArgumentException("PCEPObjectHeader is mandatory.");
+
+               logger.trace("Attempt to parse object from bytes: {}", ByteArray.bytesToHexString(bytes));
+
+               /*
+                * if PCEPObjectIdentifier.getObjectClassFromInt() don't throws
+                * exception and if Map.get() returns null, we know that we can't
+                * recognize OBJ TYPE.
+                */
+               final PCEPObjectParser objParserClass = MapOfParsers.getInstance().get(
+                       new PCEPObjectIdentifier(PCEPObjectIdentifier.ObjectClass.getFromInt(header.objClass), header.objType));
+               if (objParserClass == null) {
+                       logger.debug("Object could not be parsed. Header: {}. Body bytes: {}", header, Arrays.toString(bytes));
+                   throw new PCEPDocumentedException("Unrecognized object type: " + header.objType + " for object class: " + header.objClass,
+                           PCEPErrors.UNRECOGNIZED_OBJ_TYPE);
+               }
+               final PCEPObject obj = objParserClass.parse(bytes, header.processed, header.ignored);
+               logger.trace("Object was parsed. {}", obj);
+               return obj;
+    }
+
+    public static List<PCEPObject> parseObjects(final byte[] bytes) throws PCEPDeserializerException, PCEPDocumentedException {
+               int offset = 0;
+               final List<PCEPObject> objs = new ArrayList<PCEPObject>();
+
+               while (bytes.length - offset > 0) {
+                   if (bytes.length - offset < PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH)
+                       throw new PCEPDeserializerException("Too few bytes in passed array. Passed: " + (bytes.length - offset) + " Expected: >= "
+                               + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH + ".");
+
+                   final PCEPObjectHeader header = PCEPObjectHeader.parseHeader(Arrays.copyOfRange(bytes, offset, offset
+                           + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH));
+
+                   if (bytes.length - offset < header.objLength)
+                       throw new PCEPDeserializerException("Too few bytes in passed array. Passed: " + (bytes.length - offset) + " Expected: >= " + header.objLength
+                               + ".");
+
+                   // copy bytes for deeper parsing
+                   final byte[] bytesToPass = ByteArray.subByte(bytes, offset + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH, header.objLength
+                           - PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH);
+
+                   offset += header.objLength;
+
+                   // if obj is not-supported or unrecognized and p flag si set
+                   // adds UnknownObject to list for validation purposes
+                   try {
+                       objs.add(PCEPObjectFactory.parse(bytesToPass, header));
+                   } catch (final PCEPDocumentedException e) {
+                       if (e.getError() == PCEPErrors.UNRECOGNIZED_OBJ_CLASS | e.getError() == PCEPErrors.UNRECOGNIZED_OBJ_TYPE
+                               | e.getError() == PCEPErrors.NOT_SUPPORTED_OBJ_CLASS | e.getError() == PCEPErrors.NOT_SUPPORTED_OBJ_TYPE) {
+                           objs.add(new UnknownObject(header.processed, header.ignored, e.getError()));
+                       } else {
+                           throw e;
+                       }
+           }
+       }
+
+       return objs;
+    }
+
+    public static byte[] put(final List<PCEPObject> objects) {
+               if (objects == null || objects.isEmpty())
+                   throw new IllegalArgumentException("List<PCEPObject> is mandatory and can't be empty.");
+
+               final List<byte[]> listBytes = new ArrayList<byte[]>();
+
+               byte[] bytes;
+               int size = 0;
+               for (final PCEPObject obj : objects) {
+                   bytes = put(obj);
+                   size += bytes.length;
+                   listBytes.add(bytes);
+               }
+
+               final byte[] retBytes = new byte[size];
+
+               int offset = 0;
+               for (final byte[] bs : listBytes) {
+                   ByteArray.copyWhole(bs, retBytes, offset);
+                   offset += bs.length;
+               }
+
+               return retBytes;
+    }
+
+    private static byte[] put(final PCEPObject obj) {
+
+               byte[] objBody;
+               ObjectClass objClass;
+               int objType = 1;
+
+               if (obj instanceof PCEPOpenObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.OPEN;
+               } else if (obj instanceof PCEPRequestParameterObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.RP;
+               } else if (obj instanceof PCEPNoPathObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.NO_PATH;
+               } else if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.BANDWIDTH;
+               } else if (obj instanceof PCEPExistingPathBandwidthObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.BANDWIDTH;
+                   objType = 2;
+               } else if (obj instanceof PCEPMetricObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.METRIC;
+               } else if (obj instanceof PCEPEndPointsObject<?>) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.END_POINTS;
+                   if (((PCEPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv6Address) {
+                       objType = 2;
+                   } else if (!(((PCEPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv4Address))
+                       throw new IllegalArgumentException("Unknown instance of Source Address.");
+
+               } else if (obj instanceof PCEPP2MPEndPointsObject<?>) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.END_POINTS;
+                   objType = 3;
+                   if (((PCEPP2MPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv6Address) {
+                       objType = 4;
+                   } else if (!(((PCEPP2MPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv4Address))
+                       throw new IllegalArgumentException("Unknown instance of Source Address.");
+
+               } else if (obj instanceof PCEPUnreachedDestinationObject<?>) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.UNREACHED_DESTINATION;
+                   if (((PCEPUnreachedDestinationObject<?>) obj).getUnreachedDestinations().get(0) instanceof IPv6Address) {
+                       objType = 2;
+                   } else if (!(((PCEPUnreachedDestinationObject<?>) obj).getUnreachedDestinations().get(0) instanceof IPv4Address))
+                       throw new IllegalArgumentException("Unknown instance of Source Address.");
+
+               } else if (obj instanceof PCEPLspaObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.LSPA;
+               } else if (obj instanceof PCEPSvecObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.SVEC;
+                   objType = 1;
+               } else if (obj instanceof PCEPNotificationObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.NOTIFICATION;
+               } else if (obj instanceof PCEPErrorObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.ERROR;
+               } else if (obj instanceof PCEPCloseObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.CLOSE;
+               } else if (obj instanceof PCEPLoadBalancingObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.LOAD_BALANCING;
+               } else if (obj instanceof PCEPLspObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.LSP;
+               } else if (obj instanceof PCEPExplicitRouteObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.ERO;
+               } else if (obj instanceof PCEPReportedRouteObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.RRO;
+               } else if (obj instanceof PCEPIncludeRouteObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.IRO;
+               } else if (obj instanceof PCEPExcludeRouteObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.XRO;
+               } else if (obj instanceof PCEPObjectiveFunctionObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.OBJCETIVE_FUNCTION;
+               } else if (obj instanceof PCEPGlobalConstraintsObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.GLOBAL_CONSTRAINTS;
+               } else if (obj instanceof PCEPBranchNodeObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.BRANCH_NODE;
+                   if (obj instanceof PCEPNonBranchNodeListObject) {
+                       objType = 2;
+                   } else if (!(obj instanceof PCEPBranchNodeListObject))
+                       throw new IllegalArgumentException("Unknown instance of PCEPBranchNodeObject.");
+               } else if (obj instanceof PCEPSecondaryExplicitRouteObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.SERO;
+               } else if (obj instanceof PCEPSecondaryRecordRouteObject) {
+                   objClass = PCEPObjectIdentifier.ObjectClass.SRRO;
+               } else
+                   throw new IllegalArgumentException("Unknown instance of PCEPObject.");
+
+               final PCEPObjectParser objParserClass = MapOfParsers.getInstance().get(new PCEPObjectIdentifier(objClass, objType));
+               objBody = objParserClass.put(obj);
+
+               final byte[] objHeader = PCEPObjectHeader.putHeader(new PCEPObjectHeader(objClass.getIdentifier(), objType, objBody.length
+                       + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH, obj.isProcessed(), obj.isIgnored()));
+
+               assert objBody.length % 4 == 0 : "Wrong length of PCEPObjectBody. Passed object has length: " + objBody.length + " that is not multiple of 4.";
+
+               final byte[] retBytes = new byte[objHeader.length + objBody.length];
+               ByteArray.copyWhole(objHeader, retBytes, 0);
+               ByteArray.copyWhole(objBody, retBytes, PCEPObjectHeader.OBJ_BODY_OFFSET);
+
+               return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectHeader.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectHeader.java
new file mode 100644 (file)
index 0000000..718436a
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Header parser for {@link org.opendaylight.protocol.pcep.PCEPObject PCEPObject}
+ */
+public class PCEPObjectHeader {
+
+       private static final Logger logger = LoggerFactory.getLogger(PCEPObjectHeader.class);
+
+       /*
+        * Common object header fields lengths in bytes
+        */
+       public final static int OC_F_LENGTH = 1;
+       public final static int OT_FLAGS_MF_LENGTH = 1; // multi-field
+       public final static int OBJ_LENGTH_F_LENGTH = 2;
+
+       /*
+        * size of fields inside of multi-filed in bits
+        */
+       public final static int OT_SF_LENGTH = 4;
+       public final static int FLAGS_SF_LENGTH = 4;
+
+       /*
+        * offsets of fields inside of multi-field in bits
+        */
+       public final static int OT_SF_OFFSET = 0;
+       public final static int FLAGS_SF_OFFSET = OT_SF_OFFSET + OT_SF_LENGTH;
+
+       /*
+        * flags offsets inside multi-filed
+        */
+       public final static int P_FLAG_OFFSET = 6;
+       public final static int I_FLAG_OFFSET = 7;
+
+       /*
+        * Common object header fields offsets in bytes;
+        */
+       public final static int OC_F_OFFSET = 0;
+       public final static int OT_FLAGS_MF_OFFSET = OC_F_OFFSET + OC_F_LENGTH;
+       public final static int OBJ_LENGTH_F_OFFSET = OT_FLAGS_MF_OFFSET + OT_FLAGS_MF_LENGTH;
+       public final static int OBJ_BODY_OFFSET = OBJ_LENGTH_F_OFFSET + OBJ_LENGTH_F_LENGTH;
+
+       /*
+        * Common object header length in bytes
+        */
+       public final static int COMMON_OBJECT_HEADER_LENGTH = (OC_F_LENGTH + OT_FLAGS_MF_LENGTH + OBJ_LENGTH_F_LENGTH);
+
+       public final int objClass;
+       public final int objType;
+       public final int objLength;
+       public final boolean processed;
+       public final boolean ignored;
+
+       public PCEPObjectHeader(final int objClass, final int objType, final int objLength, final boolean processed, final boolean ignore) {
+               this.objClass = objClass;
+               this.objType = objType;
+               this.objLength = objLength;
+               this.processed = processed;
+               this.ignored = ignore;
+
+       }
+
+       public static PCEPObjectHeader parseHeader(final byte[] bytes) {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Array of bytes is mandatory.");
+
+               logger.trace("Attempt to parse object header from bytes: {}", ByteArray.bytesToHexString(bytes));
+
+               final int objClass = ByteArray.bytesToInt(Arrays.copyOfRange(bytes, OC_F_OFFSET, OC_F_OFFSET + OC_F_LENGTH));
+
+               final int objType = UnsignedBytes.toInt(ByteArray.copyBitsRange(bytes[OT_FLAGS_MF_OFFSET], OT_SF_OFFSET, OT_SF_LENGTH));
+
+               final int objLength = ByteArray.bytesToInt(Arrays.copyOfRange(bytes, OBJ_LENGTH_F_OFFSET, OBJ_LENGTH_F_OFFSET + OBJ_LENGTH_F_LENGTH));
+
+               final byte[] flagsBytes = { ByteArray.copyBitsRange(bytes[OT_FLAGS_MF_OFFSET], FLAGS_SF_OFFSET, FLAGS_SF_LENGTH) };
+
+               final BitSet flags = ByteArray.bytesToBitSet(flagsBytes);
+
+               final PCEPObjectHeader objHeader = new PCEPObjectHeader(objClass, objType, objLength, flags.get(P_FLAG_OFFSET), flags.get(I_FLAG_OFFSET));
+               logger.trace("Object header was parsed. {}", objHeader);
+               return objHeader;
+       }
+
+       public static byte[] putHeader(final PCEPObjectHeader header) {
+               if (header == null)
+                       throw new IllegalArgumentException("PCEPObjectHeader is mandatory.");
+
+               final byte[] retBytes = new byte[COMMON_OBJECT_HEADER_LENGTH];
+
+               // objClass
+               retBytes[OC_F_OFFSET] = (byte) header.objClass;
+
+               // objType_flags multi-field
+               retBytes[OT_FLAGS_MF_OFFSET] = (byte) (header.objType << (Byte.SIZE - OT_SF_LENGTH));
+               if (header.processed)
+                       retBytes[OT_FLAGS_MF_OFFSET] |= 1 << Byte.SIZE - (P_FLAG_OFFSET) - 1;
+               if (header.ignored)
+                       retBytes[OT_FLAGS_MF_OFFSET] |= 1 << Byte.SIZE - (I_FLAG_OFFSET) - 1;
+
+               // objLength
+               System.arraycopy(ByteArray.intToBytes(header.objLength), Integer.SIZE / Byte.SIZE - OBJ_LENGTH_F_LENGTH, retBytes, OBJ_LENGTH_F_OFFSET,
+                               OBJ_LENGTH_F_LENGTH);
+
+               return retBytes;
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPObjectHeader [objClass=");
+               builder.append(this.objClass);
+               builder.append(", objType=");
+               builder.append(this.objType);
+               builder.append(", objLength=");
+               builder.append(this.objLength);
+               builder.append(", processed=");
+               builder.append(this.processed);
+               builder.append(", ignored=");
+               builder.append(this.ignored);
+               builder.append("]");
+               return builder.toString();
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + (this.ignored ? 1231 : 1237);
+               result = prime * result + this.objClass;
+               result = prime * result + this.objLength;
+               result = prime * result + this.objType;
+               result = prime * result + (this.processed ? 1231 : 1237);
+               return result;
+       }
+
+       @Override
+       public boolean equals(final Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPObjectHeader other = (PCEPObjectHeader) obj;
+               if (this.ignored != other.ignored)
+                       return false;
+               if (this.objClass != other.objClass)
+                       return false;
+               if (this.objLength != other.objLength)
+                       return false;
+               if (this.objType != other.objType)
+                       return false;
+               if (this.processed != other.processed)
+                       return false;
+               return true;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectIdentifier.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectIdentifier.java
new file mode 100644 (file)
index 0000000..758590e
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.impl;
+
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+
+/**
+ * PCEP objects are identified with a couple <class, type>.
+ */
+public class PCEPObjectIdentifier {
+       /**
+        * Class identifier for {@link org.opendaylight.protocol.pcep.PCEPObject PCEPObject}
+        */
+       public static enum ObjectClass {
+               OPEN(1),
+               RP(2),
+               NO_PATH(3),
+               END_POINTS(4),
+               BANDWIDTH(5),
+               METRIC(6),
+               ERO(7),
+               RRO(8),
+               LSPA(9),
+               IRO(10),
+               SVEC(11),
+               NOTIFICATION(12),
+               ERROR(13),
+               LOAD_BALANCING(14),
+               CLOSE(15),
+               XRO(17),
+               OBJCETIVE_FUNCTION(21),
+               GLOBAL_CONSTRAINTS(24),
+               UNREACHED_DESTINATION(28),
+               SERO(29),
+               SRRO(30),
+               BRANCH_NODE(31),
+               LSP(32);
+
+               private final int identifier;
+
+               ObjectClass(final int identifier) {
+                       this.identifier = identifier;
+               }
+
+               public int getIdentifier() {
+                       return this.identifier;
+               }
+
+               public static ObjectClass getFromInt(int identifier) throws PCEPDocumentedException {
+                       for (final ObjectClass type_e : ObjectClass.values()) {
+                               if (type_e.getIdentifier() == identifier)
+                                       return type_e;
+                       }
+
+                       throw new PCEPDocumentedException("Unrecognized object class " + identifier, PCEPErrors.UNRECOGNIZED_OBJ_CLASS);
+               }
+       }
+
+       private final int objectType;
+
+       private final ObjectClass objectClass;
+
+       public PCEPObjectIdentifier(ObjectClass objectClass, int objectType) {
+               this.objectType = objectType;
+               this.objectClass = objectClass;
+       }
+
+       public int getObjectType() {
+               return this.objectType;
+       }
+
+       public ObjectClass getObjectClass() {
+               return this.objectClass;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((this.objectClass == null) ? 0 : this.objectClass.hashCode());
+               result = prime * result + this.objectType;
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (this.getClass() != obj.getClass())
+                       return false;
+               final PCEPObjectIdentifier other = (PCEPObjectIdentifier) obj;
+               if (this.objectClass != other.objectClass)
+                       return false;
+               if (this.objectType != other.objectType)
+                       return false;
+               return true;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPObjectParser.java
new file mode 100644 (file)
index 0000000..4e92586
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Interface for {@link org.opendaylight.protocol.pcep.PCEPObject PCEPObject} subobjects
+ */
+public interface PCEPObjectParser {
+       public abstract PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException;
+
+       public abstract byte[] put(PCEPObject obj);
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPRROSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPRROSubobjectParser.java
new file mode 100644 (file)
index 0000000..3957179
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.subobject.RROAttributesSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROIPv4AddressSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROIPv6AddressSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROLabelSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROPathKeyWith128PCEIDSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROPathKeyWith32PCEIDSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROProtectionSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROUnnumberedInterfaceSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.RROAttributesSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.PCEPSubobject PCEPSubobject}
+ */
+public class PCEPRROSubobjectParser {
+
+    private static final Logger logger = LoggerFactory.getLogger(PCEPRROSubobjectParser.class);
+
+    /**
+     * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPSubobject
+     * PCEPSubobject}
+     */
+    public enum PCEPSubobjectType {
+       IPv4_PREFIX(1), IPv6_PREFIX(2), LABEL(3), UNNUMBERED_INTERFACE_ID(4), ATTRIBUTES(5), PROTECTION(37), PK_32(64), PK_128(65);
+
+       private final int indicator;
+
+       PCEPSubobjectType(final int indicator) {
+           this.indicator = indicator;
+       }
+
+       public int getIndicator() {
+           return this.indicator;
+       }
+
+       public static PCEPSubobjectType getFromInt(final int type) throws PCEPDeserializerException {
+
+           for (final PCEPSubobjectType type_e : PCEPSubobjectType.values()) {
+               if (type_e.getIndicator() == type)
+                   return type_e;
+           }
+
+           throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + "; Known: " + PCEPSubobjectType.values() + ".");
+       }
+       }
+
+    /*
+     * Fields lengths in Bytes
+     */
+    public static final int TYPE_F_LENGTH = 1;
+    public static final int LENGTH_F_LENGTH = 1;
+
+    /*
+     * Fields offsets in Bytes
+     */
+    public static final int TYPE_F_OFFSET = 0;
+    public static final int LENGTH_F_OFFSET = TYPE_F_OFFSET + TYPE_F_LENGTH;
+    public static final int SO_CONTENTS_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
+
+    public static List<ReportedRouteSubobject> parse(final byte[] bytes) throws PCEPDeserializerException {
+       if (bytes == null)
+           throw new IllegalArgumentException("Byte array is mandatory.");
+
+       final List<ReportedRouteSubobject> subobjsList = new ArrayList<ReportedRouteSubobject>();
+       PCEPSubobjectType type;
+       byte[] soContentsBytes;
+       int length;
+       int offset = 0;
+
+       while (offset < bytes.length) {
+           length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
+
+           type = PCEPSubobjectType.getFromInt(bytes[offset + TYPE_F_OFFSET] & 0xff);
+
+           if (length > bytes.length - offset)
+               throw new PCEPDeserializerException("Wrong length specified. Passed: " + length + "; Expected: <= " + (bytes.length - offset));
+
+           soContentsBytes = new byte[length - SO_CONTENTS_OFFSET];
+           System.arraycopy(bytes, offset + SO_CONTENTS_OFFSET, soContentsBytes, 0, length - SO_CONTENTS_OFFSET);
+
+           logger.trace("Attempt to parse subobject from bytes: {}", ByteArray.bytesToHexString(soContentsBytes));
+           final ReportedRouteSubobject subObj = parseSpecificSubobject(type, soContentsBytes);
+           logger.trace("Subobject was parsed. {}", subObj);
+
+           subobjsList.add(subObj);
+
+           offset += length;
+       }
+
+       return subobjsList;
+    }
+
+    public static byte[] put(final List<ReportedRouteSubobject> objsToSerialize) {
+       final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
+
+       int length = 0;
+       for (final ReportedRouteSubobject obj : objsToSerialize) {
+           final byte[] bytes = put(obj);
+           length += bytes.length;
+           bytesList.add(bytes);
+       }
+
+       final byte[] retBytes = new byte[length];
+
+       int offset = 0;
+       for (final byte[] bytes : bytesList) {
+           System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
+           offset += bytes.length;
+       }
+
+       return retBytes;
+    }
+
+    public static byte[] put(final ReportedRouteSubobject objToSerialize) {
+       int typeIndicator = 0;
+
+       final byte[] soContentsBytes;
+
+       if (objToSerialize instanceof RROIPAddressSubobject<?> && ((RROIPAddressSubobject<?>) objToSerialize).getPrefix() instanceof IPv4Prefix) {
+           typeIndicator = PCEPSubobjectType.IPv4_PREFIX.getIndicator();
+           soContentsBytes = RROIPv4AddressSubobjectParser.put(objToSerialize);
+       } else if (objToSerialize instanceof RROIPAddressSubobject<?> && ((RROIPAddressSubobject<?>) objToSerialize).getPrefix() instanceof IPv6Prefix) {
+           typeIndicator = PCEPSubobjectType.IPv6_PREFIX.getIndicator();
+           soContentsBytes = RROIPv6AddressSubobjectParser.put(objToSerialize);
+       } else if (objToSerialize instanceof RROUnnumberedInterfaceSubobject) {
+           typeIndicator = PCEPSubobjectType.UNNUMBERED_INTERFACE_ID.getIndicator();
+           soContentsBytes = RROUnnumberedInterfaceSubobjectParser.put(objToSerialize);
+       } else if (objToSerialize instanceof RROLabelSubobject) {
+           typeIndicator = PCEPSubobjectType.LABEL.getIndicator();
+           soContentsBytes = RROLabelSubobjectParser.put((RROLabelSubobject) objToSerialize);
+       } else if (objToSerialize instanceof RROProtectionSubobject) {
+           typeIndicator = PCEPSubobjectType.PROTECTION.getIndicator();
+           soContentsBytes = RROProtectionSubobjectParser.put((RROProtectionSubobject) objToSerialize);
+       } else if (objToSerialize instanceof RROPathKeyWith32PCEIDSubobject) {
+           typeIndicator = PCEPSubobjectType.PK_32.getIndicator();
+           soContentsBytes = RROPathKeyWith32PCEIDSubobjectParser.put((RROPathKeyWith32PCEIDSubobject) objToSerialize);
+       } else if (objToSerialize instanceof RROPathKeyWith128PCEIDSubobject) {
+           typeIndicator = PCEPSubobjectType.PK_128.getIndicator();
+           soContentsBytes = RROPathKeyWith128PCEIDSubobjectParser.put((RROPathKeyWith128PCEIDSubobject) objToSerialize);
+       } else if (objToSerialize instanceof RROAttributesSubobject) {
+           typeIndicator = PCEPSubobjectType.ATTRIBUTES.getIndicator();
+           soContentsBytes = RROAttributesSubobjectParser.put((RROAttributesSubobject) objToSerialize);
+       } else
+           throw new IllegalArgumentException("Unknown instance of PCEPSubobject. Passed: " + objToSerialize.getClass() + ".");
+
+       final byte[] bytes = new byte[SO_CONTENTS_OFFSET + soContentsBytes.length];
+
+       bytes[TYPE_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_F_LENGTH)[0];
+       bytes[LENGTH_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(soContentsBytes.length + SO_CONTENTS_OFFSET), (Integer.SIZE / 8) - LENGTH_F_LENGTH)[0];
+
+       System.arraycopy(soContentsBytes, 0, bytes, SO_CONTENTS_OFFSET, soContentsBytes.length);
+
+       return bytes;
+    }
+
+    private static ReportedRouteSubobject parseSpecificSubobject(final PCEPSubobjectType type, final byte[] soContentsBytes) throws PCEPDeserializerException {
+
+       switch (type) {
+           case IPv4_PREFIX:
+               return RROIPv4AddressSubobjectParser.parse(soContentsBytes);
+           case IPv6_PREFIX:
+               return RROIPv6AddressSubobjectParser.parse(soContentsBytes);
+           case UNNUMBERED_INTERFACE_ID:
+               return RROUnnumberedInterfaceSubobjectParser.parse(soContentsBytes);
+           case LABEL:
+               return RROLabelSubobjectParser.parse(soContentsBytes);
+           case PROTECTION:
+               return RROProtectionSubobjectParser.parse(soContentsBytes);
+           case PK_32:
+               return RROPathKeyWith32PCEIDSubobjectParser.parse(soContentsBytes);
+           case PK_128:
+               return RROPathKeyWith128PCEIDSubobjectParser.parse(soContentsBytes);
+           case ATTRIBUTES:
+               return RROAttributesSubobjectParser.parse(soContentsBytes);
+           default:
+               throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + ".");
+       }
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionFactoryImpl.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionFactoryImpl.java
new file mode 100644 (file)
index 0000000..58798b6
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import org.opendaylight.protocol.framework.ProtocolConnection;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.SessionParent;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPSessionFactory;
+
+import java.util.Timer;
+
+public class PCEPSessionFactoryImpl implements PCEPSessionFactory {
+
+       private final int maxUnknownMessages;
+
+       public PCEPSessionFactoryImpl(final int maxUnknownMessages) {
+               this.maxUnknownMessages = maxUnknownMessages;
+       }
+
+       @Override
+       public ProtocolSession getProtocolSession(final SessionParent parent, final Timer timer,
+                       final ProtocolConnection connection, final int sessionId) {
+                return new PCEPSessionImpl(parent, timer, (PCEPConnection)connection, new PCEPMessageFactory(),
+                                this.maxUnknownMessages, sessionId);
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionImpl.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionImpl.java
new file mode 100644 (file)
index 0000000..f867462
--- /dev/null
@@ -0,0 +1,765 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolOutputStream;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.SessionParent;
+import org.opendaylight.protocol.pcep.PCEPCloseTermination;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPErrorTermination;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.impl.message.PCEPRawMessage;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * Implementation of PCEPSession. (Not final for testing.)
+ */
+class PCEPSessionImpl implements PCEPSession, ProtocolSession, PCEPSessionRuntimeMXBean {
+
+       /**
+        * KeepAlive Timer is to be scheduled periodically, each time it starts, it sends KeepAlive Message.
+        */
+       private class KeepAliveTimer extends TimerTask {
+               private final PCEPSessionImpl parent;
+
+               public KeepAliveTimer(final PCEPSessionImpl parent) {
+                       this.parent = parent;
+               }
+
+               @Override
+               public void run() {
+                       this.parent.handleKeepaliveTimer();
+               }
+       }
+
+       /**
+        * DeadTimer is to be scheduled periodically, when it expires, it closes PCEP session.
+        */
+       private class DeadTimer extends TimerTask {
+               private final PCEPSessionImpl parent;
+
+               public DeadTimer(final PCEPSessionImpl parent) {
+                       this.parent = parent;
+               }
+
+               @Override
+               public void run() {
+                       this.parent.handleDeadtimer();
+               }
+       }
+
+       /**
+        * OpenWaitTimer runs just once, but can be rescheduled or canceled before expiration. When it expires, it sends an
+        * error message (1, 2)
+        */
+       private class OpenWaitTimer extends TimerTask {
+
+               private final PCEPSessionImpl parent;
+
+               public OpenWaitTimer(final PCEPSessionImpl parent) {
+                       this.parent = parent;
+               }
+
+               @Override
+               public void run() {
+                       this.parent.handleOpenWait();
+               }
+       }
+
+       /**
+        * KeepWaitTimer runs just once, but can be rescheduled or canceled before expiration. When it expires, it sends an
+        * error message (1, 7)
+        */
+       private class KeepWaitTimer extends TimerTask {
+
+               private final PCEPSessionImpl parent;
+
+               public KeepWaitTimer(final PCEPSessionImpl parent) {
+                       this.parent = parent;
+               }
+
+               @Override
+               public void run() {
+                       this.parent.handleKeepWait();
+               }
+       }
+
+       /**
+        * Possible states for Finite State Machine
+        */
+       private enum State {
+               IDLE, OPEN_WAIT, KEEP_WAIT, UP
+       }
+
+       /**
+        * In seconds.
+        */
+       public static final int OPEN_WAIT_TIMER_VALUE = 60;
+
+       public static final int KEEP_WAIT_TIMER_VALUE = 60;
+
+       public int KEEP_ALIVE_TIMER_VALUE = 3;
+
+       public int DEAD_TIMER_VALUE = 4 * this.KEEP_ALIVE_TIMER_VALUE;
+
+       /**
+        * Actual state of the FSM.
+        */
+       private State state;
+
+       private OpenWaitTimer openWaitTimer;
+
+       private KeepWaitTimer keepWaitTimer;
+
+       /**
+        * System.nanoTime value about when was sent the last message Protected to be updated also in tests.
+        */
+       protected long lastMessageSentAt;
+
+       /**
+        * System.nanoTime value about when was received the last message
+        */
+       private long lastMessageReceivedAt;
+
+       private boolean localOK = false;
+
+       private boolean remoteOK = false;
+
+       private boolean openRetry = false;
+
+       private final int sessionId;
+
+       /**
+        * Protected for testing.
+        */
+       protected int maxUnknownMessages = 5;
+
+       protected final Queue<Long> unknownMessagesTimes = new LinkedList<Long>();
+
+       private final PCEPSessionListener listener;
+
+       private PCEPSessionProposalChecker checker = null;
+
+       /**
+        * Open Object with session characteristics that were accepted by another PCE (sent from this session).
+        */
+       private PCEPOpenObject localOpen = null;
+
+       /**
+        * Open Object with session characteristics for this session (sent from another PCE).
+        */
+       private PCEPOpenObject remoteOpen = null;
+
+       private final ProtocolOutputStream outputStream;
+
+       private static final Logger logger = LoggerFactory.getLogger(PCEPSessionImpl.class);
+
+       /**
+        * Timer object grouping FSM Timers
+        */
+       private final Timer stateTimer;
+
+       private final SessionParent parent;
+
+       private final PCEPMessageFactory factory;
+
+       private int sentMsgCount = 0;
+
+       private int receivedMsgCount = 0;
+
+       private final String peerAddress;
+
+       PCEPSessionImpl(final SessionParent parent, final Timer timer, final PCEPConnection connection, final PCEPMessageFactory factory,
+                       final int maxUnknownMessages, final int sessionId) {
+               this.state = State.IDLE;
+               this.listener = connection.getListener();
+               this.checker = connection.getProposalChecker();
+               this.sessionId = sessionId;
+               this.localOpen = connection.getProposal().getOpenObject();
+               this.outputStream = new ProtocolOutputStream();
+               this.peerAddress = connection.getPeerAddress().getHostString();
+               this.stateTimer = timer;
+               this.parent = parent;
+               this.factory = factory;
+               if (this.maxUnknownMessages != 0)
+                       this.maxUnknownMessages = maxUnknownMessages;
+       }
+
+       @Override
+       public void startSession() {
+               logger.debug("Session started.");
+               this.sendMessage(new PCEPOpenMessage(this.localOpen));
+               this.restartOpenWait();
+               this.changeState(State.OPEN_WAIT);
+       }
+
+       /**
+        * OpenWait timer can be canceled or rescheduled before its expiration. When it expires, it sends particular
+        * PCEPErrorMessage and closes PCEP session.
+        */
+       private synchronized void handleOpenWait() {
+               if (this.state != State.IDLE) {
+                       this.terminate(PCEPErrors.NO_OPEN_BEFORE_EXP_OPENWAIT); // 1, 1
+               }
+       }
+
+       /**
+        * KeepWait timer can be canceled or rescheduled before its expiration. When it expires, it sends particular
+        * PCEPErrorMessage and closes PCEP session.
+        */
+       private synchronized void handleKeepWait() {
+               if (this.state != State.IDLE) {
+                       this.terminate(PCEPErrors.NO_MSG_BEFORE_EXP_KEEPWAIT); // 1, 7
+               }
+       }
+
+       /**
+        * If DeadTimer expires, the session ends. If a message (whichever) was received during this period, the DeadTimer
+        * will be rescheduled by DEAD_TIMER_VALUE + the time that has passed from the start of the DeadTimer to the time at
+        * which the message was received. If the session was closed by the time this method starts to execute (the session
+        * state will become IDLE), that rescheduling won't occur.
+        */
+       private synchronized void handleDeadtimer() {
+               final long ct = System.nanoTime();
+
+               final long nextDead = (long) (this.lastMessageReceivedAt + (this.DEAD_TIMER_VALUE * 1E9));
+
+               if (this.state != State.IDLE) {
+                       if (ct >= nextDead) {
+                               logger.debug("DeadTimer expired. " + new Date());
+                               this.terminate(Reason.EXP_DEADTIMER);
+                               return;
+                       }
+
+                       this.stateTimer.schedule(new DeadTimer(this), (long) ((nextDead - ct) / 1E6));
+               }
+       }
+
+       /**
+        * If KeepAlive Timer expires, sends KeepAlive message. If a message (whichever) was send during this period, the
+        * KeepAlive Timer will be rescheduled by KEEP_ALIVE_TIMER_VALUE + the time that has passed from the start of the
+        * KeepAlive timer to the time at which the message was sent. If the session was closed by the time this method
+        * starts to execute (the session state will become IDLE), that rescheduling won't occur.
+        */
+       private synchronized void handleKeepaliveTimer() {
+               final long ct = System.nanoTime();
+
+               long nextKeepalive = (long) (this.lastMessageSentAt + (this.KEEP_ALIVE_TIMER_VALUE * 1E9));
+
+               if (this.state != State.IDLE) {
+                       if (ct >= nextKeepalive) {
+                               this.sendMessage(new PCEPKeepAliveMessage());
+                               nextKeepalive = (long) (this.lastMessageSentAt + (this.KEEP_ALIVE_TIMER_VALUE * 1E9));
+                       }
+
+                       this.stateTimer.schedule(new KeepAliveTimer(this), (long) ((nextKeepalive - ct) / 1E6));
+               }
+       }
+
+       private void changeState(final State finalState) {
+               switch (finalState) {
+               case IDLE:
+                       logger.debug("Changed to state: " + State.IDLE);
+                       this.state = State.IDLE;
+                       return;
+               case OPEN_WAIT:
+                       logger.debug("Changed to state: " + State.OPEN_WAIT);
+                       if (this.state == State.UP) {
+                               throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.OPEN_WAIT);
+                       }
+                       this.state = State.OPEN_WAIT;
+                       return;
+               case KEEP_WAIT:
+                       logger.debug("Changed to state: " + State.KEEP_WAIT);
+                       if (this.state == State.UP || this.state == State.IDLE) {
+                               throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.KEEP_WAIT);
+                       }
+                       this.state = State.KEEP_WAIT;
+                       return;
+               case UP:
+                       logger.debug("Changed to state: " + State.UP);
+                       if (this.state == State.IDLE || this.state == State.UP) {
+                               throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.UP);
+                       }
+                       this.state = State.UP;
+                       return;
+               }
+       }
+
+       private void restartOpenWait() {
+               if (this.state == State.OPEN_WAIT && this.openWaitTimer != null) {
+                       this.openWaitTimer.cancel();
+               }
+               this.openWaitTimer = new OpenWaitTimer(this);
+               this.stateTimer.schedule(this.openWaitTimer, OPEN_WAIT_TIMER_VALUE * 1000);
+       }
+
+       private void restartKeepWaitTimer() {
+               if (this.state == State.KEEP_WAIT && this.keepWaitTimer != null) {
+                       this.keepWaitTimer.cancel();
+               }
+               this.keepWaitTimer = new KeepWaitTimer(this);
+               this.stateTimer.schedule(this.keepWaitTimer, KEEP_WAIT_TIMER_VALUE * 1000);
+       }
+
+       /**
+        * Makes a callback to check if the session characteristics that FSM received, are acceptable.
+        *
+        * @param keepAliveTimerValue
+        * @param deadTimerValue
+        * @param tlvs
+        * @return
+        */
+       private boolean checkSessionCharacteristics(final PCEPOpenObject openObj) {
+               return this.checker.checkSessionCharacteristics(new PCEPSessionPreferences(openObj));
+       }
+
+       private PCEPOpenObject getNewProposal() {
+               return this.checker.getNewProposal(new PCEPSessionPreferences(this.localOpen)).getOpenObject();
+       }
+
+       /**
+        * Sends message to serialization.
+        *
+        * @param msg to be sent
+        */
+       @Override
+       public void sendMessage(final PCEPMessage msg) {
+               this.outputStream.putMessage(msg, this.factory);
+               this.lastMessageSentAt = System.nanoTime();
+               if (!(msg instanceof PCEPKeepAliveMessage))
+                       logger.debug("Sent message: " + msg);
+               this.parent.checkOutputBuffer(this);
+               this.sentMsgCount++;
+       }
+
+       @Override
+       public ProtocolOutputStream getStream() {
+               return this.outputStream;
+       }
+
+       private void commonClose() {
+               this.changeState(State.IDLE);
+               this.parent.onSessionClosed(this);
+       }
+
+       /**
+        * Closes PCEP session from the parent with given reason. A message needs to be sent, but parent doesn't have to be
+        * modified, because he initiated the closing. (To prevent concurrent modification exception).
+        *
+        * @param closeObject
+        */
+       void closeWithoutMessage() {
+               logger.debug("Closing session: {}", this);
+               commonClose();
+       }
+
+       /**
+        * Closes PCEP session, cancels all timers, returns to state Idle WITHOUT sending the Close Message. KeepAlive and
+        * DeadTimer are cancelled if the state of the session changes to IDLE. This method is used to close the PCEP
+        * session from inside the session or from the listener, therefore the parent of this session should be informed.
+        * The only closing reason is UNKNOWN.
+        */
+       @Override
+       public synchronized void close() {
+               logger.debug("Closing session: {}", this);
+               this.sendMessage(new PCEPCloseMessage(new PCEPCloseObject(Reason.UNKNOWN)));
+               commonClose();
+       }
+
+       private void terminate(final PCEPCloseObject.Reason reason) {
+               this.sendMessage(new PCEPCloseMessage(new PCEPCloseObject(reason)));
+               this.closeWithoutMessage();
+               this.listener.onSessionTerminated(this, new PCEPCloseTermination(reason));
+       }
+
+       private void terminate(final PCEPErrors error) {
+               this.sendErrorMessage(error);
+               this.closeWithoutMessage();
+               this.listener.onSessionTerminated(this, new PCEPErrorTermination(error));
+       }
+
+       @Override
+       public void endOfInput() {
+               if (this.state != State.IDLE) {
+                       this.listener.onSessionDown(this, null, new IOException("End of input detected. Close the session."));
+               }
+       }
+
+       @Override
+       public int maximumMessageSize() {
+               return 65535;
+       }
+
+       private void sendErrorMessage(final PCEPErrors value) {
+               this.sendErrorMessage(value, null);
+       }
+
+       /**
+        * Sends PCEP Error Message with one PCEPError and Open Object.
+        *
+        * @param value
+        * @param open
+        */
+       private void sendErrorMessage(final PCEPErrors value, final PCEPOpenObject open) {
+               final PCEPErrorObject error = new PCEPErrorObject(value);
+               final List<PCEPErrorObject> errors = new ArrayList<PCEPErrorObject>();
+               errors.add(error);
+               this.sendMessage(new PCEPErrorMessage(open, errors, null));
+       }
+
+       @Override
+       public void handleMalformedMessage(final DeserializerException e) {
+               // FIXME rewrite
+
+       }
+
+       @Override
+       public void handleMalformedMessage(final DocumentedException e) {
+               // FIXME rewrite
+
+       }
+
+       /**
+        * The fact, that a message is malformed, comes from parser. In case of unrecognized message a particular error is
+        * sent (CAPABILITY_NOT_SUPPORTED) and the method checks if the MAX_UNKNOWN_MSG per minute wasn't overstepped.
+        * Second, any other error occurred that is specified by rfc. In this case, the an error message is generated and
+        * sent.
+        *
+        * @param error documented error in RFC5440 or draft
+        */
+       public void handleMalformedMessage(final PCEPErrors error) {
+               final long ct = System.nanoTime();
+               this.sendErrorMessage(error);
+               if (error == PCEPErrors.CAPABILITY_NOT_SUPPORTED) {
+                       this.unknownMessagesTimes.add(ct);
+                       while (ct - this.unknownMessagesTimes.peek() > 60 * 1E9) {
+                               this.unknownMessagesTimes.poll();
+                       }
+                       if (this.unknownMessagesTimes.size() > this.maxUnknownMessages) {
+                               this.terminate(Reason.TOO_MANY_UNKNOWN_MSG);
+                       }
+               }
+       }
+
+       /**
+        * In case of syntactic error or some parsing error, the session needs to be closed with the Reason: malformed
+        * message. The user needs to be notified about this error.
+        *
+        * @param e exception that was thrown from parser
+        */
+       public void handleMalformedMessage(final Exception e) {
+               logger.warn("PCEP byte stream corruption detected", e);
+               this.terminate(Reason.MALFORMED_MSG);
+       }
+
+       /**
+        * Open message should be handled only if the FSM is in OPEN_WAIT state.
+        *
+        * @param msg
+        */
+       private void handleOpenMessage(final PCEPOpenMessage msg) {
+               this.remoteOpen = msg.getOpenObject();
+               logger.debug("Received message: " + msg.toString());
+               if (this.state != State.OPEN_WAIT) {
+                       this.sendErrorMessage(PCEPErrors.ATTEMPT_2ND_SESSION);
+                       return;
+               }
+               final Boolean result = this.checkSessionCharacteristics(this.remoteOpen);
+               if (result == null) {
+                       this.terminate(PCEPErrors.NON_ACC_NON_NEG_SESSION_CHAR); // 1, 3
+                       return;
+               } else if (result) {
+                       this.DEAD_TIMER_VALUE = this.remoteOpen.getDeadTimerValue();
+                       this.KEEP_ALIVE_TIMER_VALUE = this.remoteOpen.getKeepAliveTimerValue();
+                       logger.debug("Session chars are acceptable. Overwriting: deadtimer: " + this.DEAD_TIMER_VALUE + "keepalive: "
+                                       + this.KEEP_ALIVE_TIMER_VALUE);
+                       this.remoteOK = true;
+                       this.openWaitTimer.cancel();
+                       this.sendMessage(new PCEPKeepAliveMessage());
+                       // if the timer is not disabled
+                       if (this.KEEP_ALIVE_TIMER_VALUE != 0) {
+                               this.stateTimer.schedule(new KeepAliveTimer(this), this.KEEP_ALIVE_TIMER_VALUE * 1000);
+                       }
+                       if (this.localOK) {
+                               // if the timer is not disabled
+                               if (this.DEAD_TIMER_VALUE != 0) {
+                                       this.stateTimer.schedule(new DeadTimer(this), this.DEAD_TIMER_VALUE * 1000);
+                               }
+                               this.changeState(State.UP);
+                               this.listener.onSessionUp(this, this.localOpen, this.remoteOpen);
+                       } else {
+                               this.restartKeepWaitTimer();
+                               this.changeState(State.KEEP_WAIT);
+                       }
+                       return;
+               } else if (!result) {
+                       this.localOpen = this.getNewProposal();
+                       if (this.openRetry) {
+                               this.terminate(PCEPErrors.SECOND_OPEN_MSG); // 1, 5
+                       } else {
+                               this.openRetry = true;
+                               this.sendErrorMessage(PCEPErrors.NON_ACC_NEG_SESSION_CHAR, this.localOpen); // 1, 4
+                               if (this.localOK) {
+                                       this.restartOpenWait();
+                                       this.changeState(State.OPEN_WAIT);
+                               } else {
+                                       this.restartKeepWaitTimer();
+                                       this.changeState(State.KEEP_WAIT);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Error message should be handled in FSM if its state is KEEP_WAIT, otherwise it is just passed to session listener
+        * for handling.
+        *
+        * @param msg
+        */
+       private void handleErrorMessage(final PCEPErrorMessage msg) {
+               this.remoteOpen = msg.getOpenObject();
+               final Boolean result = this.checkSessionCharacteristics(this.remoteOpen);
+               if (result == null || !result) {
+                       this.terminate(PCEPErrors.PCERR_NON_ACC_SESSION_CHAR); // 1, 6
+                       return;
+               } else {
+                       this.KEEP_ALIVE_TIMER_VALUE = this.remoteOpen.getKeepAliveTimerValue();
+                       this.DEAD_TIMER_VALUE = this.remoteOpen.getDeadTimerValue();
+                       logger.debug("New values for keepalive: " + this.remoteOpen.getKeepAliveTimerValue() + " deadtimer "
+                                       + this.remoteOpen.getDeadTimerValue());
+                       this.sendMessage(new PCEPOpenMessage(this.remoteOpen));
+                       if (this.remoteOK) {
+                               this.restartKeepWaitTimer();
+                               this.changeState(State.KEEP_WAIT);
+                       } else {
+                               this.keepWaitTimer.cancel();
+                               this.restartOpenWait();
+                               this.changeState(State.OPEN_WAIT);
+                       }
+               }
+       }
+
+       /**
+        * KeepAlive message should be explicitly parsed in FSM when its state is KEEP_WAIT. Otherwise is handled by the
+        * KeepAliveTimer or it's invalid.
+        */
+       private void handleKeepAliveMessage() {
+               if (this.state == State.KEEP_WAIT) {
+                       this.localOK = true;
+                       this.keepWaitTimer.cancel();
+                       if (this.remoteOK) {
+                               if (this.DEAD_TIMER_VALUE != 0) {
+                                       this.stateTimer.schedule(new DeadTimer(this), this.DEAD_TIMER_VALUE * 1000);
+                               }
+                               this.changeState(State.UP);
+                               this.listener.onSessionUp(this, this.localOpen, this.remoteOpen);
+                       } else {
+                               this.restartOpenWait();
+                               this.changeState(State.OPEN_WAIT);
+                       }
+               }
+       }
+
+       /**
+        * Handles incoming message. If the session is up, it notifies the user. The user is notified about every message
+        * except KeepAlive.
+        *
+        * @param msg incoming message
+        */
+       @Override
+       public void handleMessage(final ProtocolMessage msg) {
+               // Update last reception time
+               final PCEPMessage pcepMsg = (PCEPMessage) msg;
+
+               this.lastMessageReceivedAt = System.nanoTime();
+               this.receivedMsgCount++;
+
+               if (pcepMsg instanceof PCEPRawMessage) {
+                       List<PCEPMessage> msgs;
+                       try {
+                               msgs = PCEPMessageValidator.getValidator(((PCEPRawMessage) pcepMsg).getMsgType()).validate(
+                                               ((PCEPRawMessage) pcepMsg).getAllObjects());
+                               for (final PCEPMessage tmpMsg : msgs) {
+                                       this.handleMessage(tmpMsg);
+                               }
+                       } catch (final PCEPDeserializerException e) {
+                               logger.error("Malformed message, terminating. ", e);
+                               this.terminate(Reason.MALFORMED_MSG);
+                       }
+                       return;
+               }
+
+               // Keepalives are handled internally
+               if (pcepMsg instanceof PCEPKeepAliveMessage) {
+                       this.handleKeepAliveMessage();
+                       return;
+               }
+
+               // Open messages are handled internally
+               if (pcepMsg instanceof PCEPOpenMessage) {
+                       this.handleOpenMessage((PCEPOpenMessage) pcepMsg);
+                       return;
+               }
+
+               /*
+                * During initial handshake we handle all the messages.
+                */
+               if (this.state != State.UP) {
+                       /*
+                        * In KEEP_WAIT, an Error message is a valid thing to see, because
+                        * it is used in negotiation.
+                        */
+                       if (pcepMsg instanceof PCEPErrorMessage && this.state == State.KEEP_WAIT
+                                       && ((PCEPErrorMessage) pcepMsg).getOpenObject() != null) {
+                               this.handleErrorMessage((PCEPErrorMessage) pcepMsg);
+                               return;
+                       }
+
+                       /*
+                        * OPEN and KEEPALIVE messages are handled at the top. ERROR
+                        * messages are handled in the specific case of KEEP_WAIT above, so
+                        * anything else is invalid here.
+                        */
+                       this.terminate(PCEPErrors.NON_OR_INVALID_OPEN_MSG);
+                       return;
+               }
+
+               /*
+                * Session is up, we are reporting all messages to user. One notable
+                * exception is CLOSE message, which needs to be converted into a
+                * session DOWN event.
+                */
+               if (pcepMsg instanceof PCEPCloseMessage) {
+                       this.listener.onSessionTerminated(this, new PCEPCloseTermination(((PCEPCloseMessage) pcepMsg).getCloseObject().getReason()));
+                       this.closeWithoutMessage();
+                       return;
+               }
+               this.listener.onMessage(this, pcepMsg);
+       }
+
+       @Override
+       public ProtocolMessageFactory getMessageFactory() {
+               return this.factory;
+       }
+
+       @Override
+       public void onConnectionFailed(final IOException e) {
+               logger.info("Connection failed before finishing: {}", e.getMessage(), e);
+               this.listener.onSessionDown(this, new PCEPCloseObject(Reason.UNKNOWN), e);
+       }
+
+       /**
+        * @return the sentMsgCount
+        */
+
+       @Override
+       public Integer getSentMsgCount() {
+               return this.sentMsgCount;
+       }
+
+       /**
+        * @return the receivedMsgCount
+        */
+
+       @Override
+       public Integer getReceivedMsgCount() {
+               return this.receivedMsgCount;
+       }
+
+
+       @Override
+       public Integer getDeadTimerValue() {
+               return this.DEAD_TIMER_VALUE;
+       }
+
+
+       @Override
+       public Integer getKeepAliveTimerValue() {
+               return this.KEEP_ALIVE_TIMER_VALUE;
+       }
+
+
+       @Override
+       public String getPeerAddress() {
+               return this.peerAddress;
+       }
+
+       @Override
+       public void tearDown() throws IOException {
+               this.close();
+       }
+
+
+       @Override
+       public String getNodeIdentifier() {
+               if (!this.remoteOpen.getTlvs().isEmpty()) {
+                       final PCEPTlv tlv = this.remoteOpen.getTlvs().iterator().next();
+                       if (tlv != null && tlv instanceof NodeIdentifierTlv) {
+                               return tlv.toString();
+                       }
+               }
+               return "";
+       }
+
+       @Override
+       public String toString() {
+               final StringBuilder builder = new StringBuilder();
+               builder.append("PCEPSessionImpl [state=");
+               builder.append(this.state);
+               builder.append(", localOK=");
+               builder.append(this.localOK);
+               builder.append(", remoteOK=");
+               builder.append(this.remoteOK);
+               builder.append(", openRetry=");
+               builder.append(this.openRetry);
+               builder.append(", sessionId=");
+               builder.append(this.sessionId);
+               builder.append(", checker=");
+               builder.append(this.checker);
+               builder.append(", localOpen=");
+               builder.append(this.localOpen);
+               builder.append(", remoteOpen=");
+               builder.append(this.remoteOpen);
+               builder.append(", outputStream=");
+               builder.append(this.outputStream);
+               builder.append("]");
+               return builder.toString();
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionProposalCheckerFactoryImpl.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionProposalCheckerFactoryImpl.java
new file mode 100644 (file)
index 0000000..493c4aa
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalCheckerFactory;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+public class PCEPSessionProposalCheckerFactoryImpl extends
+               PCEPSessionProposalCheckerFactory  implements Closeable {
+
+       @Override
+       public PCEPSessionProposalChecker getPreferencesChecker(
+                       final InetSocketAddress address) {
+               return new PCEPSessionProposalChecker() {
+
+                       @Override
+                       public Boolean checkSessionCharacteristics(
+                                       final SessionPreferences openObj) {
+                               return true;
+                       }
+
+                       @Override
+                       public PCEPSessionPreferences getNewProposal(
+                                       final SessionPreferences open) {
+                               return new PCEPSessionPreferences(new PCEPOpenObject(30, 120, 0, null));
+                       }
+
+               };
+       }
+
+       @Override
+       public void close() throws IOException {
+               // nothing to close
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionProposalFactoryImpl.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionProposalFactoryImpl.java
new file mode 100644 (file)
index 0000000..cc78347
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposal;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.tlv.LSPCleanupTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+
+public class PCEPSessionProposalFactoryImpl extends PCEPSessionProposalFactory implements Closeable {
+
+       private final int keepAlive, deadTimer, timeout;
+
+       private final boolean stateful, active, versioned, instant;
+
+       public PCEPSessionProposalFactoryImpl(final int deadTimer, final int keepAlive, final boolean stateful, final boolean active, final boolean versioned, final boolean instant, final int timeout) {
+               this.deadTimer = deadTimer;
+               this.keepAlive = keepAlive;
+               this.stateful = stateful;
+               this.active = active;
+               this.versioned = versioned;
+               this.instant = instant;
+               this.timeout = timeout;
+       }
+
+       @Override
+       public PCEPSessionProposal getSessionProposal(final InetSocketAddress address, final int sessionId) {
+               return new PCEPSessionProposal() {
+
+                       @Override
+                       public PCEPSessionPreferences getProposal() {
+                               List<PCEPTlv> tlvs = null;
+                               if (PCEPSessionProposalFactoryImpl.this.stateful) {
+                                       tlvs = new ArrayList<PCEPTlv>();
+                                       tlvs.add(new PCEStatefulCapabilityTlv(PCEPSessionProposalFactoryImpl.this.instant, PCEPSessionProposalFactoryImpl.this.active, PCEPSessionProposalFactoryImpl.this.versioned));
+                                       if (PCEPSessionProposalFactoryImpl.this.instant) {
+                                               tlvs.add(new LSPCleanupTlv(PCEPSessionProposalFactoryImpl.this.timeout));
+                                       }
+                               }
+                               return new PCEPSessionPreferences(new PCEPOpenObject(PCEPSessionProposalFactoryImpl.this.keepAlive, PCEPSessionProposalFactoryImpl.this.deadTimer, sessionId, tlvs));
+                       }
+
+               };
+       }
+
+       public int getKeepAlive() {
+               return this.keepAlive;
+       }
+
+       public int getDeadTimer() {
+               return this.deadTimer;
+       }
+
+       public boolean isStateful() {
+               return this.stateful;
+       }
+
+       public boolean isActive() {
+               return this.active;
+       }
+
+       public boolean isVersioned() {
+               return this.versioned;
+       }
+
+       public boolean isInstant() {
+               return this.instant;
+       }
+
+       public int getTimeout() {
+               return this.timeout;
+       }
+
+       @Override
+       public void close() throws IOException {
+               // nothing to close
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionRuntimeMXBean.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionRuntimeMXBean.java
new file mode 100644 (file)
index 0000000..e51fdf7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.io.IOException;
+
+public interface PCEPSessionRuntimeMXBean {
+       //TODO remove once operations are generated
+
+       Integer getDeadTimerValue();
+
+       Integer getKeepAliveTimerValue();
+
+       Integer getReceivedMsgCount();
+
+       Integer getSentMsgCount();
+
+       String getPeerAddress();
+
+       String getNodeIdentifier();
+
+       void tearDown() throws IOException;
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPTlvParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPTlvParser.java
new file mode 100644 (file)
index 0000000..99a7740
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+import org.opendaylight.protocol.pcep.impl.tlv.LSPIdentifierIPv4TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.LSPIdentifierIPv6TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.NoPathVectorTlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.OFListTlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.PCEStatefulCapabilityTlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.RSVPErrorSpecIPv4TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.RSVPErrorSpecIPv6TlvParser;
+import org.opendaylight.protocol.pcep.tlv.IPv4LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.IPv6LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPCleanupTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPSymbolicNameTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPUpdateErrorTlv;
+import org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import org.opendaylight.protocol.pcep.tlv.OFListTlv;
+import org.opendaylight.protocol.pcep.tlv.OrderTlv;
+import org.opendaylight.protocol.pcep.tlv.OverloadedDurationTlv;
+import org.opendaylight.protocol.pcep.tlv.P2MPCapabilityTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+import org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv;
+import org.opendaylight.protocol.pcep.tlv.ReqMissingTlv;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.PCEPTlv PCEPTlv} and its subclasses
+ */
+public final class PCEPTlvParser {
+
+    private static final Logger logger = LoggerFactory.getLogger(PCEPTlvParser.class);
+
+    /**
+     * Type indicator for {@link org.opendaylight.protocol.pcep.PCEPTlv PCEPTlv}
+     */
+    private enum PCEPTlvType {
+       NO_PATH_VECTOR(1),
+       OVERLOADED_DURATION(2),
+       REQ_MISSING(3),
+       OF_LIST_TLV(4),
+       ORDER_TLV(5),
+       P2MP_CAPABILITY(6),
+       PCE_STATEFUL_CAPABILITY(16),
+       LSP_SYMBOLIC_NAME(17),
+       LSP_IDENTIFIER_IPV4(18),
+       LSP_IDENTIFIER_IPV6(19),
+       LSP_UPDATE_ERROR(20),
+       RSVP_ERROR_SPEC_IPV4(21),
+       RSVP_ERROR_SPEC_IPV6(22),
+       LSP_STATE_DB_VERSION(23),
+       // TODO: use IANA defined number - for now has been used first unused
+       // number
+       NODE_IDENTIFIER(24),
+       LSP_CLEANUP_TLV(26);
+
+       private final int indicator;
+
+       PCEPTlvType(final int indicator) {
+           this.indicator = indicator;
+       }
+
+       public int getIndicator() {
+           return this.indicator;
+       }
+
+       public static PCEPTlvType getFromInt(final int type) throws PCEPDeserializerException {
+
+           for (final PCEPTlvType type_e : PCEPTlvType.values()) {
+               if (type_e.getIndicator() == type)
+                   return type_e;
+           }
+
+           throw new PCEPDeserializerException("Unknown TLV type: " + type);
+       }
+       }
+
+    /*
+     * Fields lengths in Bytes
+     */
+    public static final int TYPE_F_LENGTH = 2;
+    public static final int LENGTH_F_LENGTH = 2;
+    public static final int HEADER_LENGTH = LENGTH_F_LENGTH + TYPE_F_LENGTH;
+
+    /*
+     * Fields offsets in Bytes
+     */
+    public static final int TYPE_F_OFFSET = 0;
+    public static final int LENGTH_F_OFFSET = TYPE_F_OFFSET + TYPE_F_LENGTH;
+    public static final int VALUE_F_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
+
+    /*
+     * padding of value field in bytes
+     */
+    public static final int PADDED_TO = 4;
+
+    /*
+     * constants for specific one-value tlvs
+     */
+    private static final int DBV_F_LENGTH = 8;
+    private static final int OVERLOADED_DURATION_LENGTH = 4;
+    private static final int UPDATE_ERR_CODE_LENGTH = 4;
+    private static final int REQ_ID_LENGTH = 4;
+    private static final int ORDR_DEL_LENGTH = 4;
+    private static final int ORDR_SETUP_LENGTH = 4;
+    private static final int P2MP_CAPABLITY_LENGTH = 2;
+
+    public static List<PCEPTlv> parse(final byte[] bytes) throws PCEPDeserializerException {
+       if (bytes == null)
+           throw new IllegalArgumentException("Byte array is mandatory.");
+
+       final List<PCEPTlv> tlvList = new ArrayList<PCEPTlv>();
+       PCEPTlvType type;
+       int length;
+       int offset = 0;
+
+       while (offset + HEADER_LENGTH < bytes.length) {
+
+           length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
+
+           type = PCEPTlvType.getFromInt(ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + TYPE_F_OFFSET, TYPE_F_LENGTH)));
+
+           if (HEADER_LENGTH + length > bytes.length - offset)
+               throw new PCEPDeserializerException("Wrong length specified. Passed: " + (HEADER_LENGTH + length) + "; Expected: <= " + (bytes.length - offset)
+                       + ".");
+
+           final byte[] tlvBytes = ByteArray.subByte(bytes, offset + VALUE_F_OFFSET, length);
+
+           logger.trace("Attempt to parse tlv from bytes: {}", ByteArray.bytesToHexString(tlvBytes));
+           final PCEPTlv tlv = parseSpecificTLV(type, tlvBytes);
+           logger.trace("Tlv was parsed. {}", tlv);
+
+           tlvList.add(tlv);
+
+           offset += HEADER_LENGTH + length + Util.getPadding(HEADER_LENGTH + length, PADDED_TO);
+       }
+
+       return tlvList;
+    }
+
+    public static byte[] put(final List<PCEPTlv> objsToSerialize) {
+       final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
+
+       int length = 0;
+       for (final PCEPTlv obj : objsToSerialize) {
+           final byte[] bytes = put(obj);
+           length += bytes.length;
+           bytesList.add(bytes);
+       }
+
+       final byte[] retBytes = new byte[length];
+
+       int offset = 0;
+       for (final byte[] bytes : bytesList) {
+           System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
+           offset += bytes.length;
+       }
+
+       return retBytes;
+    }
+
+    public static byte[] put(final PCEPTlv objToSerialize) {
+       int typeIndicator = 0;
+
+       byte[] valueBytes;
+
+       if (objToSerialize instanceof PCEStatefulCapabilityTlv) {
+           typeIndicator = PCEPTlvType.PCE_STATEFUL_CAPABILITY.getIndicator();
+           valueBytes = PCEStatefulCapabilityTlvParser.serializeValueField((PCEStatefulCapabilityTlv) objToSerialize);
+       } else if (objToSerialize instanceof LSPStateDBVersionTlv) {
+           typeIndicator = PCEPTlvType.LSP_STATE_DB_VERSION.getIndicator();
+           valueBytes = ByteArray.longToBytes(((LSPStateDBVersionTlv) objToSerialize).getDbVersion());
+       } else if (objToSerialize instanceof NoPathVectorTlv) {
+           typeIndicator = PCEPTlvType.NO_PATH_VECTOR.getIndicator();
+           valueBytes = NoPathVectorTlvParser.put((NoPathVectorTlv) objToSerialize);
+       } else if (objToSerialize instanceof OverloadedDurationTlv) {
+           typeIndicator = PCEPTlvType.OVERLOADED_DURATION.getIndicator();
+           valueBytes = ByteArray.intToBytes(((OverloadedDurationTlv) objToSerialize).getValue());
+       } else if (objToSerialize instanceof LSPSymbolicNameTlv) {
+           typeIndicator = PCEPTlvType.LSP_SYMBOLIC_NAME.getIndicator();
+           valueBytes = ((LSPSymbolicNameTlv) objToSerialize).getSymbolicName().getSymbolicName();
+       } else if (objToSerialize instanceof LSPUpdateErrorTlv) {
+           typeIndicator = PCEPTlvType.LSP_UPDATE_ERROR.getIndicator();
+           valueBytes = ((LSPUpdateErrorTlv) objToSerialize).getErrorCode();
+
+           assert valueBytes.length == UPDATE_ERR_CODE_LENGTH : "Update error code si too large.";
+
+       } else if (objToSerialize instanceof IPv4LSPIdentifiersTlv) {
+           typeIndicator = PCEPTlvType.LSP_IDENTIFIER_IPV4.getIndicator();
+           valueBytes = LSPIdentifierIPv4TlvParser.put((IPv4LSPIdentifiersTlv) objToSerialize);
+       } else if (objToSerialize instanceof IPv6LSPIdentifiersTlv) {
+           typeIndicator = PCEPTlvType.LSP_IDENTIFIER_IPV6.getIndicator();
+           valueBytes = LSPIdentifierIPv6TlvParser.put((IPv6LSPIdentifiersTlv) objToSerialize);
+       } else if (objToSerialize instanceof RSVPErrorSpecTlv<?> && ((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress() instanceof IPv4Address) {
+           typeIndicator = PCEPTlvType.RSVP_ERROR_SPEC_IPV4.getIndicator();
+           valueBytes = RSVPErrorSpecIPv4TlvParser.put((RSVPErrorSpecTlv<?>) objToSerialize);
+       } else if (objToSerialize instanceof RSVPErrorSpecTlv<?> && ((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress() instanceof IPv6Address) {
+           typeIndicator = PCEPTlvType.RSVP_ERROR_SPEC_IPV6.getIndicator();
+           valueBytes = RSVPErrorSpecIPv6TlvParser.put((RSVPErrorSpecTlv<?>) objToSerialize);
+       } else if (objToSerialize instanceof ReqMissingTlv) {
+           typeIndicator = PCEPTlvType.REQ_MISSING.getIndicator();
+           valueBytes = new byte[REQ_ID_LENGTH];
+           System.arraycopy(ByteArray.longToBytes(((ReqMissingTlv) objToSerialize).getRequestID()), Long.SIZE / Byte.SIZE - REQ_ID_LENGTH, valueBytes, 0,
+                   REQ_ID_LENGTH);
+       } else if (objToSerialize instanceof NodeIdentifierTlv) {
+           typeIndicator = PCEPTlvType.NODE_IDENTIFIER.getIndicator();
+           valueBytes = ((NodeIdentifierTlv) objToSerialize).getValue();
+       } else if (objToSerialize instanceof OrderTlv) {
+           typeIndicator = PCEPTlvType.ORDER_TLV.getIndicator();
+           valueBytes = new byte[ORDR_DEL_LENGTH + ORDR_SETUP_LENGTH];
+           ByteArray.copyWhole(ByteArray.intToBytes((int) ((OrderTlv) objToSerialize).getDeleteOrder()), valueBytes, 0);
+           ByteArray.copyWhole(ByteArray.intToBytes((int) ((OrderTlv) objToSerialize).getSetupOrder()), valueBytes, ORDR_DEL_LENGTH);
+       } else if (objToSerialize instanceof P2MPCapabilityTlv) {
+           typeIndicator = PCEPTlvType.P2MP_CAPABILITY.getIndicator();
+           valueBytes = new byte[P2MP_CAPABLITY_LENGTH];
+           ByteArray.copyWhole(ByteArray.shortToBytes((short) ((P2MPCapabilityTlv) objToSerialize).getValue()), valueBytes, 0);
+       } else if (objToSerialize instanceof OFListTlv) {
+           typeIndicator = PCEPTlvType.OF_LIST_TLV.getIndicator();
+           valueBytes = OFListTlvParser.put((OFListTlv) objToSerialize);
+       } else if (objToSerialize instanceof LSPCleanupTlv) {
+           typeIndicator = PCEPTlvType.LSP_CLEANUP_TLV.getIndicator();
+           valueBytes = ByteArray.intToBytes(((LSPCleanupTlv) objToSerialize).getTimeout());
+       } else
+           throw new IllegalArgumentException("Unknown instance of PCEPTlv. Passed: " + objToSerialize + ".");
+
+       final byte[] typeBytes = ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_F_LENGTH);
+       final byte[] lengthBytes = ByteArray.cutBytes(ByteArray.intToBytes(valueBytes.length), (Integer.SIZE / 8) - LENGTH_F_LENGTH);
+       final byte[] bytes = new byte[HEADER_LENGTH + valueBytes.length + Util.getPadding(HEADER_LENGTH + valueBytes.length, PADDED_TO)];
+
+       System.arraycopy(typeBytes, 0, bytes, TYPE_F_OFFSET, TYPE_F_LENGTH);
+       System.arraycopy(lengthBytes, 0, bytes, LENGTH_F_OFFSET, LENGTH_F_LENGTH);
+       System.arraycopy(valueBytes, 0, bytes, VALUE_F_OFFSET, valueBytes.length);
+
+       return bytes;
+    }
+
+    private static PCEPTlv parseSpecificTLV(final PCEPTlvType type, final byte[] valueBytes) throws PCEPDeserializerException {
+       switch (type) {
+           case PCE_STATEFUL_CAPABILITY:
+               return PCEStatefulCapabilityTlvParser.deserializeValueField(valueBytes);
+           case LSP_STATE_DB_VERSION:
+               return new LSPStateDBVersionTlv(ByteArray.bytesToLong(ByteArray.subByte(valueBytes, 0, DBV_F_LENGTH)));
+           case NO_PATH_VECTOR:
+               return NoPathVectorTlvParser.parse(valueBytes);
+           case OVERLOADED_DURATION:
+               return new OverloadedDurationTlv(ByteArray.bytesToInt(ByteArray.subByte(valueBytes, 0, OVERLOADED_DURATION_LENGTH)));
+           case LSP_SYMBOLIC_NAME:
+               return new LSPSymbolicNameTlv(new LSPSymbolicName(valueBytes));
+           case LSP_UPDATE_ERROR:
+               return new LSPUpdateErrorTlv(valueBytes);
+           case LSP_IDENTIFIER_IPV4:
+               return LSPIdentifierIPv4TlvParser.parse(valueBytes);
+           case LSP_IDENTIFIER_IPV6:
+               return LSPIdentifierIPv6TlvParser.parse(valueBytes);
+           case RSVP_ERROR_SPEC_IPV4:
+               return RSVPErrorSpecIPv4TlvParser.parse(valueBytes);
+           case RSVP_ERROR_SPEC_IPV6:
+               return RSVPErrorSpecIPv6TlvParser.parse(valueBytes);
+           case REQ_MISSING:
+               return new ReqMissingTlv(ByteArray.bytesToLong(ByteArray.subByte(valueBytes, 0, REQ_ID_LENGTH)));
+           case NODE_IDENTIFIER:
+               return new NodeIdentifierTlv(valueBytes);
+           case ORDER_TLV:
+               return new OrderTlv(ByteArray.bytesToLong(ByteArray.subByte(valueBytes, 0, ORDR_DEL_LENGTH)), ByteArray.bytesToLong(ByteArray.subByte(
+                       valueBytes, ORDR_DEL_LENGTH, ORDR_SETUP_LENGTH)));
+           case P2MP_CAPABILITY:
+               return new P2MPCapabilityTlv(ByteArray.bytesToShort(ByteArray.subByte(valueBytes, 0, P2MP_CAPABLITY_LENGTH)) & 0xFFFF);
+           case OF_LIST_TLV:
+               return OFListTlvParser.parse(valueBytes);
+           case LSP_CLEANUP_TLV:
+               return new LSPCleanupTlv(ByteArray.bytesToInt(valueBytes));
+           default:
+               throw new PCEPDeserializerException("Unknown TLV type. Passed: " + type + ";");
+       }
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPXROSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPXROSubobjectParser.java
new file mode 100644 (file)
index 0000000..5b274b7
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.subobject.XROAsNumberSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROIPv4PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROIPv6PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROSRLGSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROUnnumberedInterfaceSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.PCEPXROSubobject PCEPXROSubobject}
+ */
+public class PCEPXROSubobjectParser {
+
+       private static final Logger logger = LoggerFactory.getLogger(PCEPXROSubobjectParser.class);
+
+       /**
+        * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPXROSubobject
+        * PCEPXROSubobject}
+        */
+       public enum PCEPXROSubobjectType {
+               IPv4_PREFIX(1), IPv6_PREFIX(2), UNNUMBERED_INTERFACE_ID(4), AS_NUMBER(32), SRLG(34);
+
+               private final int indicator;
+
+               PCEPXROSubobjectType(int indicator) {
+                       this.indicator = indicator;
+               }
+
+               public int getIndicator() {
+                       return this.indicator;
+               }
+
+               public static PCEPXROSubobjectType getFromInt(int type) throws PCEPDeserializerException {
+
+                       for (final PCEPXROSubobjectType type_e : PCEPXROSubobjectType.values()) {
+                               if (type_e.getIndicator() == type)
+                                       return type_e;
+                       }
+
+                       throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + "; Known: " + PCEPXROSubobjectType.values() + ".");
+               }
+       }
+
+       /*
+        * Fields lengths in Bytes
+        */
+       public static final int TYPE_FLAG_F_LENGTH = 1;
+       public static final int LENGTH_F_LENGTH = 1;
+
+       /*
+        * Fields offsets in Bytes
+        */
+       public static final int TYPE_FLAG_F_OFFSET = 0;
+       public static final int LENGTH_F_OFFSET = TYPE_FLAG_F_OFFSET + TYPE_FLAG_F_LENGTH;
+       public static final int SO_CONTENTS_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
+
+       public static List<ExcludeRouteSubobject> parse(byte[] bytes) throws PCEPDeserializerException {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Byte array is mandatory.");
+
+               final List<ExcludeRouteSubobject> subobjsList = new ArrayList<ExcludeRouteSubobject>();
+               boolean mandatoryFlag;
+               PCEPXROSubobjectType type;
+               byte[] soContentsBytes;
+               int length;
+               int offset = 0;
+
+               while (offset < bytes.length) {
+
+                       mandatoryFlag = ((bytes[offset + TYPE_FLAG_F_OFFSET] & (1 << 7)) != 0);
+                       length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
+
+                       type = PCEPXROSubobjectType.getFromInt((bytes[offset + TYPE_FLAG_F_OFFSET] & 0xff) & ~(1 << 7));
+
+                       if (length > bytes.length - offset)
+                               throw new PCEPDeserializerException("Wrong length specified. Passed: " + length + "; Expected: <= " + (bytes.length - offset));
+
+                       soContentsBytes = new byte[length - SO_CONTENTS_OFFSET];
+                       System.arraycopy(bytes, offset + SO_CONTENTS_OFFSET, soContentsBytes, 0, length - SO_CONTENTS_OFFSET);
+
+                       logger.debug("Attempt to parse exclude route objects subobject from bytes: {}", ByteArray.bytesToHexString(soContentsBytes));
+                       final ExcludeRouteSubobject subObj = parseSpecificSubobject(type, soContentsBytes, mandatoryFlag);
+                       logger.debug("Subobject was parsed. {}", subObj);
+
+                       subobjsList.add(subObj);
+
+                       offset += length;
+               }
+
+               return subobjsList;
+       }
+
+       public static byte[] put(List<ExcludeRouteSubobject> objsToSerialize) {
+               final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
+
+               int length = 0;
+               for (final ExcludeRouteSubobject obj : objsToSerialize) {
+                       final byte[] bytes = put(obj);
+                       length += bytes.length;
+                       bytesList.add(bytes);
+               }
+
+               final byte[] retBytes = new byte[length];
+
+               int offset = 0;
+               for (final byte[] bytes : bytesList) {
+                       System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
+                       offset += bytes.length;
+               }
+
+               return retBytes;
+       }
+
+       public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+               int typeIndicator = 0;
+
+               final byte[] soContentsBytes;
+
+               if (objToSerialize instanceof XROIPPrefixSubobject<?> && ((XROIPPrefixSubobject<?>) objToSerialize).getPrefix() instanceof IPv4Prefix) {
+                       typeIndicator = PCEPXROSubobjectType.IPv4_PREFIX.getIndicator();
+                       soContentsBytes = XROIPv4PrefixSubobjectParser.put(objToSerialize);
+               } else if (objToSerialize instanceof XROIPPrefixSubobject<?> && ((XROIPPrefixSubobject<?>) objToSerialize).getPrefix() instanceof IPv6Prefix) {
+                       typeIndicator = PCEPXROSubobjectType.IPv6_PREFIX.getIndicator();
+                       soContentsBytes = XROIPv6PrefixSubobjectParser.put(objToSerialize);
+               } else if (objToSerialize instanceof XROAsNumberSubobject) {
+                       typeIndicator = PCEPXROSubobjectType.AS_NUMBER.getIndicator();
+                       soContentsBytes = XROAsNumberSubobjectParser.put(objToSerialize);
+               } else if (objToSerialize instanceof XROUnnumberedInterfaceSubobject) {
+                       typeIndicator = PCEPXROSubobjectType.UNNUMBERED_INTERFACE_ID.getIndicator();
+                       soContentsBytes = XROUnnumberedInterfaceSubobjectParser.put(objToSerialize);
+               } else if (objToSerialize instanceof XROSRLGSubobject) {
+                       typeIndicator = PCEPXROSubobjectType.SRLG.getIndicator();
+                       soContentsBytes = XROSRLGSubobjectParser.put(objToSerialize);
+               } else
+                       throw new IllegalArgumentException("Unknown instance of PCEPXROSubobject. Passed: " + objToSerialize.getClass() + ".");
+
+               final byte[] bytes = new byte[SO_CONTENTS_OFFSET + soContentsBytes.length];
+
+               bytes[TYPE_FLAG_F_OFFSET] = (byte) (ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_FLAG_F_LENGTH)[0] | (objToSerialize
+                               .isMandatory() ? 1 << 7 : 0));
+               bytes[LENGTH_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(soContentsBytes.length + SO_CONTENTS_OFFSET), (Integer.SIZE / 8) - LENGTH_F_LENGTH)[0];
+
+               System.arraycopy(soContentsBytes, 0, bytes, SO_CONTENTS_OFFSET, soContentsBytes.length);
+
+               return bytes;
+       }
+
+       private static ExcludeRouteSubobject parseSpecificSubobject(PCEPXROSubobjectType type, byte[] soContentsBytes, boolean mandatory)
+                       throws PCEPDeserializerException {
+
+               switch (type) {
+                       case IPv4_PREFIX:
+                               return XROIPv4PrefixSubobjectParser.parse(soContentsBytes, mandatory);
+                       case IPv6_PREFIX:
+                               return XROIPv6PrefixSubobjectParser.parse(soContentsBytes, mandatory);
+                       case UNNUMBERED_INTERFACE_ID:
+                               return XROUnnumberedInterfaceSubobjectParser.parse(soContentsBytes, mandatory);
+                       case AS_NUMBER:
+                               return XROAsNumberSubobjectParser.parse(soContentsBytes, mandatory);
+                       case SRLG:
+                               return XROSRLGSubobjectParser.parse(soContentsBytes, mandatory);
+                       default:
+                               throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + ".");
+               }
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/Util.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/Util.java
new file mode 100644 (file)
index 0000000..c4b936f
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.AddressFamily;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * Utilities used in pcep-impl
+ */
+public final class Util {
+
+       private Util() {
+       }
+
+       public static class BiParsersMap<K, KV, V> {
+               private final HashMap<K, KV> kToKv = new HashMap<K, KV>();
+
+               private final HashMap<KV, V> kvToV = new HashMap<KV, V>();
+
+               public void put(K key, KV keyValue, V value) {
+                       this.kToKv.put(key, keyValue);
+                       this.kvToV.put(keyValue, value);
+               }
+
+               public KV getKeyValueFromKey(K key) {
+                       return this.kToKv.get(key);
+               }
+
+               public V getValueFromKeyValue(KV keyValue) {
+                       return this.kvToV.get(keyValue);
+               }
+       }
+
+       public static int getPadding(int length, int padding) {
+               return (padding - (length % padding)) % padding;
+       }
+
+       public static <T extends NetworkAddress<T>> List<T> parseAddresses(byte[] bytes, int offset, AddressFamily<T> family, int addrLen) {
+               final List<T> addresses = new ArrayList<T>();
+
+               while (bytes.length > offset) {
+                       addresses.add(family.addressForBytes(ByteArray.subByte(bytes, offset, addrLen)));
+                       offset += addrLen;
+               }
+
+               return addresses;
+       }
+
+       public static <T extends NetworkAddress<T>> void putAddresses(byte[] destBytes, int offset, List<T> addresses, int addrLen) {
+               for (final T address : addresses) {
+                       System.arraycopy(address.getAddress(), 0, destBytes, offset, addrLen);
+                       offset += addrLen;
+               }
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCCreateMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCCreateMessageParser.java
new file mode 100644 (file)
index 0000000..f0953d9
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCCreateMessage;
+
+/**
+ * Parser for {@link PCCreateMessage}
+ */
+public class PCCreateMessageParser implements PCEPMessageParser {
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.opendaylight.protocol.pcep.impl.PCEPMessageParser#put(org.opendaylight.protocol.pcep.PCEPMessage
+        * )
+        */
+       @Override
+       public byte[] put(PCEPMessage msg) {
+               if (!(msg instanceof PCCreateMessage))
+                       throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Needed PCCreateMessage.");
+
+               return PCEPObjectFactory.put(((PCCreateMessage) msg).getAllObjects());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCCreateMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCCreateMessageValidator.java
new file mode 100644 (file)
index 0000000..891fd8a
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCCreateMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.object.CompositeInstantiationObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+
+/**
+ * PCCCreateMessage validator. Validates message integrity.
+ */
+public class PCCreateMessageValidator extends PCEPMessageValidator {
+
+    @Override
+    public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+       if (objects == null)
+           throw new IllegalArgumentException("Passed list can't be null.");
+
+       final List<CompositeInstantiationObject> insts = new ArrayList<CompositeInstantiationObject>();
+
+       CompositeInstantiationObject inst;
+       while (!objects.isEmpty()) {
+           try {
+               if ((inst = this.getValidInstantiationObject(objects)) == null)
+                   break;
+           } catch (final PCEPDocumentedException e) {
+               return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+           }
+
+           insts.add(inst);
+       }
+
+       if (insts.isEmpty())
+           throw new PCEPDeserializerException("At least one CompositeInstantiationObject is mandatory.");
+
+       if (!objects.isEmpty())
+           throw new PCEPDeserializerException("Unprocessed objects: " + objects);
+
+       return Arrays.asList((PCEPMessage) new PCCreateMessage(insts));
+    }
+
+    private CompositeInstantiationObject getValidInstantiationObject(List<PCEPObject> objects) throws PCEPDocumentedException {
+       if (objects.get(0) instanceof UnknownObject)
+           throw new PCEPDocumentedException("Unknown object", ((UnknownObject) objects.get(0)).getError());
+       if (!(objects.get(0) instanceof PCEPEndPointsObject<?>))
+           return null;
+
+       final PCEPEndPointsObject<?> endPoints = ((PCEPEndPointsObject<?>) objects.get(0));
+       objects.remove(0);
+
+       if (objects.get(0) instanceof UnknownObject)
+           throw new PCEPDocumentedException("Unknown object", ((UnknownObject) objects.get(0)).getError());
+       if (!(objects.get(0) instanceof PCEPLspaObject))
+           throw new PCEPDocumentedException("LSPA Object must be second.", PCEPErrors.LSPA_MISSING);
+       final PCEPLspaObject lspa = (PCEPLspaObject) objects.get(0);
+       objects.remove(0);
+
+       PCEPExplicitRouteObject ero = null;
+       PCEPRequestedPathBandwidthObject bandwidth = null;
+       final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+       PCEPObject obj;
+       int state = 1;
+       while (!objects.isEmpty()) {
+           obj = objects.get(0);
+           if (obj instanceof UnknownObject) {
+               throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+           }
+
+           switch (state) {
+               case 1:
+                   state = 2;
+                   if (obj instanceof PCEPExplicitRouteObject) {
+                       ero = (PCEPExplicitRouteObject) obj;
+                       break;
+                   }
+               case 2:
+                   state = 3;
+                   if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                       bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+                       break;
+                   }
+               case 3:
+                   state = 4;
+                   if (obj instanceof PCEPMetricObject) {
+                       metrics.add((PCEPMetricObject) obj);
+                       state = 3;
+                       break;
+                   }
+           }
+
+           if (state == 4)
+               break;
+
+           objects.remove(0);
+       }
+
+       return new CompositeInstantiationObject(endPoints, lspa, ero, bandwidth, metrics);
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPCloseMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPCloseMessageParser.java
new file mode 100644 (file)
index 0000000..9f280e5
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPCloseMessage
+ * PCEPCloseMessage}
+ */
+public class PCEPCloseMessageParser implements PCEPMessageParser {
+
+    @Override
+    public byte[] put(PCEPMessage msg) {
+       if (!(msg instanceof PCEPCloseMessage))
+           throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPCloseMessage.");
+
+       return PCEPObjectFactory.put(((PCEPCloseMessage) msg).getAllObjects());
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPCloseMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPCloseMessageValidator.java
new file mode 100644 (file)
index 0000000..bd46b85
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+
+/**
+ * PCEPCloseMessage validator. Validates message integrity.
+ */
+public class PCEPCloseMessageValidator extends PCEPMessageValidator {
+
+       @Override
+       public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+               if (objects == null)
+                       throw new IllegalArgumentException("Passed list can't be null.");
+
+               if (objects.isEmpty() || !(objects.get(0) instanceof PCEPCloseObject))
+                       throw new PCEPDeserializerException("Close message doesn't contain CLOSE object.");
+
+               final PCEPCloseMessage msg = new PCEPCloseMessage((PCEPCloseObject) objects.get(0));
+               objects.remove(0);
+
+               if (!objects.isEmpty())
+                       throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+               return new ArrayList<PCEPMessage>() {
+                       private static final long serialVersionUID = 1L;
+                       {
+                               this.add(msg);
+                       }
+               };
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPErrorMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPErrorMessageParser.java
new file mode 100644 (file)
index 0000000..6ebc315
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPErrorMessage
+ * PCEPErrorMessage}
+ */
+public class PCEPErrorMessageParser implements PCEPMessageParser {
+
+       @Override
+       public byte[] put(PCEPMessage msg) {
+               if (!(msg instanceof PCEPErrorMessage))
+                       throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance " + msg.getClass() + ". Nedded PCEPErrorMessage.");
+
+               return PCEPObjectFactory.put(((PCEPErrorMessage) msg).getAllObjects());
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPErrorMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPErrorMessageValidator.java
new file mode 100644 (file)
index 0000000..df6942e
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+
+/**
+ * PCEPErrorMessage validator. Validates message integrity.
+ */
+public class PCEPErrorMessageValidator extends PCEPMessageValidator {
+
+       @Override
+       public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+               if (objects == null)
+                       throw new IllegalArgumentException("Passed list can't be null.");
+
+               PCEPOpenObject openObj = null;
+               final List<CompositeErrorObject> errors = new ArrayList<CompositeErrorObject>();
+               final List<PCEPErrorObject> errorObjects = new ArrayList<PCEPErrorObject>();
+
+               PCEPObject obj;
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       obj = objects.get(0);
+
+                       if (obj instanceof UnknownObject)
+                               return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(((UnknownObject) obj).getError())));
+
+                       switch (state) {
+                               case 1:
+                                       if (obj instanceof PCEPErrorObject) {
+                                               errorObjects.add((PCEPErrorObject) obj);
+                                               break;
+                                       }
+                                       state = 2;
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPOpenObject) {
+                                               openObj = (PCEPOpenObject) obj;
+                                               break;
+                                       }
+                               case 3:
+                                       while (!objects.isEmpty()) {
+                                               CompositeErrorObject comObj;
+
+                                               try {
+                                                       comObj = getValidErrorComposite(objects);
+                                               } catch (final PCEPDocumentedException e) {
+                                                       return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+                                               }
+
+                                               if (comObj == null)
+                                                       break;
+
+                                               errors.add(comObj);
+                                       }
+
+                                       state = 4;
+                                       break;
+                       }
+
+                       if (state == 4) {
+                               break;
+                       }
+
+                       objects.remove(0);
+               }
+
+               if (errors.isEmpty() && errorObjects.isEmpty())
+                       throw new PCEPDeserializerException("At least one PCEPErrorObject is mandatory.");
+
+               if (!objects.isEmpty())
+                       throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+               return Arrays.asList((PCEPMessage) new PCEPErrorMessage(openObj, errorObjects, errors));
+       }
+
+       private static CompositeErrorObject getValidErrorComposite(List<PCEPObject> objects) throws PCEPDocumentedException, PCEPDeserializerException {
+               final List<PCEPRequestParameterObject> requestParameters = new ArrayList<PCEPRequestParameterObject>();
+               final List<PCEPErrorObject> errors = new ArrayList<PCEPErrorObject>();
+               PCEPObject obj;
+               int state = 1;
+
+               while (!objects.isEmpty()) {
+                       obj = objects.get(0);
+
+                       if (obj instanceof UnknownObject)
+                               throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPRequestParameterObject) {
+                                               if (((PCEPRequestParameterObject) obj).isProcessed())
+                                                       throw new PCEPDocumentedException("Invalid setting of P flag.", PCEPErrors.P_FLAG_NOT_SET);
+                                               requestParameters.add((PCEPRequestParameterObject) obj);
+                                               state = 1;
+                                               break;
+                                       }
+                               case 2:
+                                       if (obj instanceof PCEPErrorObject) {
+                                               errors.add((PCEPErrorObject) obj);
+                                               state = 2;
+                                               break;
+                                       }
+                                       state = 3;
+                       }
+
+                       if (state == 3)
+                               break;
+
+                       objects.remove(0);
+               }
+
+               if (errors.isEmpty())
+                       return null;
+
+               return new CompositeErrorObject(requestParameters, errors);
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPKeepAliveMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPKeepAliveMessageParser.java
new file mode 100644 (file)
index 0000000..89fa5cd
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage
+ * PCEPKeepAliveMessage}
+ */
+public class PCEPKeepAliveMessageParser implements PCEPMessageParser {
+
+       @Override
+       public byte[] put(PCEPMessage msg) {
+               if (!(msg instanceof PCEPKeepAliveMessage))
+                       throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPKeepAliveMessage.");
+
+               return new byte[0];
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPKeepAliveMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPKeepAliveMessageValidator.java
new file mode 100644 (file)
index 0000000..c989d0b
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+
+/**
+ * PCEPKeepAliveMessage validator. Validates message integrity.
+ */
+public class PCEPKeepAliveMessageValidator extends PCEPMessageValidator {
+
+       @Override
+       public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+               if (objects != null && !objects.isEmpty())
+                       throw new PCEPDeserializerException("KeepAlive message has content.");
+
+               return new ArrayList<PCEPMessage>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new PCEPKeepAliveMessage());
+                       }
+               };
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPNotificationMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPNotificationMessageParser.java
new file mode 100644 (file)
index 0000000..280ed17
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPNotificationMessage
+ * PCEPNotificationMessage}
+ */
+public class PCEPNotificationMessageParser implements PCEPMessageParser {
+
+       @Override
+       public byte[] put(PCEPMessage msg) {
+               if (!(msg instanceof PCEPNotificationMessage))
+                       throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Needed PCEPNotificationMessage.");
+
+               return PCEPObjectFactory.put(((PCEPNotificationMessage) msg).getAllObjects());
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPNotificationMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPNotificationMessageValidator.java
new file mode 100644 (file)
index 0000000..056fe57
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+
+/**
+ * PCEPNotificationMessage validator. Validates message integrity.
+ */
+public class PCEPNotificationMessageValidator extends PCEPMessageValidator {
+
+       @Override
+       public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+               if (objects == null)
+                       throw new IllegalArgumentException("Passed list can't be null.");
+
+               final List<CompositeNotifyObject> compositeNotifications = new ArrayList<CompositeNotifyObject>();
+
+               while (!objects.isEmpty()) {
+                       CompositeNotifyObject comObj;
+                       try {
+                               comObj = getValidNotificationComposite(objects);
+                       } catch (final PCEPDocumentedException e) {
+                               return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+                       }
+
+                       if (comObj == null)
+                               break;
+
+                       compositeNotifications.add(comObj);
+               }
+
+               if (compositeNotifications.isEmpty())
+                       throw new PCEPDeserializerException("Atleast one CompositeNotifiObject is mandatory.");
+
+               if (!objects.isEmpty())
+                       throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+               return Arrays.asList((PCEPMessage) new PCEPNotificationMessage(compositeNotifications));
+       }
+
+       private static CompositeNotifyObject getValidNotificationComposite(List<PCEPObject> objects) throws PCEPDocumentedException {
+               final List<PCEPRequestParameterObject> requestParameters = new ArrayList<PCEPRequestParameterObject>();
+               final List<PCEPNotificationObject> notifications = new ArrayList<PCEPNotificationObject>();
+               PCEPObject obj;
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       obj = objects.get(0);
+
+                       if (obj instanceof UnknownObject)
+                               throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPRequestParameterObject) {
+                                               if (((PCEPRequestParameterObject) obj).isProcessed())
+                                                       throw new PCEPDocumentedException("Invalid setting of P flag.", PCEPErrors.P_FLAG_NOT_SET);
+                                               requestParameters.add((PCEPRequestParameterObject) obj);
+                                               state = 1;
+                                               break;
+                                       }
+                               case 2:
+                                       if (obj instanceof PCEPNotificationObject) {
+                                               notifications.add((PCEPNotificationObject) obj);
+                                               state = 2;
+                                               break;
+                                       }
+                                       state = 3;
+                       }
+
+                       if (state == 3)
+                               break;
+
+                       objects.remove(obj);
+               }
+
+               if (notifications.isEmpty())
+                       return null;
+
+               return new CompositeNotifyObject(requestParameters, notifications);
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPOpenMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPOpenMessageParser.java
new file mode 100644 (file)
index 0000000..3377604
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPOpenMessage PCEPOpenMessage}
+ */
+public class PCEPOpenMessageParser implements PCEPMessageParser {
+
+    @Override
+    public byte[] put(PCEPMessage msg) {
+       if (!(msg instanceof PCEPOpenMessage))
+           throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance " + msg.getClass() + ". Nedded PCEPOpenMessage.");
+
+       return PCEPObjectFactory.put(((PCEPOpenMessage) msg).getAllObjects());
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPOpenMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPOpenMessageValidator.java
new file mode 100644 (file)
index 0000000..47105ea
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * PCEPOpenMessage validator. Validates message integrity.
+ */
+public class PCEPOpenMessageValidator extends PCEPMessageValidator {
+
+       @Override
+       public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+               if (objects == null)
+                       throw new IllegalArgumentException("Passed list can't be null.");
+
+               if (objects.isEmpty() || !(objects.get(0) instanceof PCEPOpenObject))
+                       throw new PCEPDeserializerException("Open message doesn't contain OPEN object.");
+
+               final PCEPOpenMessage msg = new PCEPOpenMessage((PCEPOpenObject) objects.get(0));
+               objects.remove(0);
+
+               if (!objects.isEmpty())
+                       throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+               return new ArrayList<PCEPMessage>() {
+                       private static final long serialVersionUID = 1L;
+                       {
+                               this.add(msg);
+                       }
+               };
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPRawMessage.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPRawMessage.java
new file mode 100644 (file)
index 0000000..2abd9c8
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageFactory.PCEPMessageType;
+
+/**
+ * Class representing raw message.
+ */
+public class PCEPRawMessage extends PCEPMessage {
+
+       private static final long serialVersionUID = 1075879993862417873L;
+
+       private final PCEPMessageType msgType;
+
+       public PCEPRawMessage(List<PCEPObject> objects, PCEPMessageType msgType) {
+               super(objects);
+               this.msgType = msgType;
+       }
+
+       public PCEPMessageType getMsgType() {
+               return this.msgType;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReplyMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReplyMessageParser.java
new file mode 100644 (file)
index 0000000..637386f
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPReplyMessage
+ * PCEPReplyMessage}
+ */
+public class PCEPReplyMessageParser implements PCEPMessageParser {
+
+       @Override
+       public byte[] put(PCEPMessage msg) {
+               if (!(msg instanceof PCEPReplyMessage))
+                       throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPReplyMessage.");
+
+               return PCEPObjectFactory.put(((PCEPReplyMessage) msg).getAllObjects());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReplyMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReplyMessageValidator.java
new file mode 100644 (file)
index 0000000..fe7befb
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositePathObject;
+import org.opendaylight.protocol.pcep.object.CompositeReplySvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+
+/**
+ * PCEPReplyMessage validator. Validates message integrity.
+ */
+public class PCEPReplyMessageValidator extends PCEPMessageValidator {
+
+       private static class SubReplyValidator {
+
+               private boolean requestRejected = true;
+
+               private List<PCEPMessage> msgs = new ArrayList<PCEPMessage>();
+
+               private PCEPRequestParameterObject rpObj;
+
+               private PCEPNoPathObject noPath;
+               private PCEPLspObject lsp;
+               private PCEPLspaObject lspa;
+               private PCEPRequestedPathBandwidthObject bandwidth;
+               private List<PCEPMetricObject> metrics;
+               private PCEPIncludeRouteObject iro;
+               private List<CompositePathObject> paths;
+
+               private void init() {
+                       this.requestRejected = false;
+                       this.msgs = new ArrayList<PCEPMessage>();
+
+                       this.noPath = null;
+                       this.lsp = null;
+                       this.lspa = null;
+                       this.iro = null;
+                       this.rpObj = null;
+                       this.metrics = new ArrayList<PCEPMetricObject>();
+                       this.paths = new ArrayList<CompositePathObject>();
+               }
+
+               public List<PCEPMessage> validate(List<PCEPObject> objects, List<CompositeReplySvecObject> svecList) {
+                       this.init();
+
+                       if (!(objects.get(0) instanceof PCEPRequestParameterObject))
+                               return null;
+
+                       final PCEPRequestParameterObject rpObj = (PCEPRequestParameterObject) objects.get(0);
+                       objects.remove(0);
+
+                       PCEPObject obj;
+                       int state = 1;
+                       while (!objects.isEmpty()) {
+                               obj = objects.get(0);
+                               if (obj instanceof UnknownObject) {
+                                       if (((UnknownObject) obj).isProcessed()) {
+                                               this.msgs.add(new PCEPErrorMessage(
+                                                               new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(((UnknownObject) obj).getError()))));
+                                               this.requestRejected = true;
+                                       }
+
+                                       objects.remove(0);
+                                       continue;
+                               }
+
+                               switch (state) {
+                                       case 1:
+                                               state = 2;
+                                               if (obj instanceof PCEPNoPathObject) {
+                                                       this.noPath = (PCEPNoPathObject) obj;
+                                                       break;
+                                               }
+                                       case 2:
+                                               state = 3;
+                                               if (obj instanceof PCEPLspObject) {
+                                                       this.lsp = (PCEPLspObject) obj;
+                                                       break;
+                                               }
+                                       case 3:
+                                               state = 4;
+                                               if (obj instanceof PCEPLspaObject) {
+                                                       this.lspa = (PCEPLspaObject) obj;
+                                                       break;
+                                               }
+                                       case 4:
+                                               state = 5;
+                                               if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                                                       this.bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+                                                       break;
+                                               }
+                                       case 5:
+                                               state = 6;
+                                               if (obj instanceof PCEPMetricObject) {
+                                                       this.metrics.add((PCEPMetricObject) obj);
+                                                       state = 5;
+                                                       break;
+                                               }
+                                       case 6:
+                                               state = 7;
+                                               if (obj instanceof PCEPIncludeRouteObject) {
+                                                       this.iro = (PCEPIncludeRouteObject) obj;
+                                                       state = 8;
+                                                       break;
+                                               }
+                               }
+
+                               if (state == 7)
+                                       break;
+
+                               objects.remove(0);
+
+                               if (state == 8)
+                                       break;
+                       }
+
+                       if (!objects.isEmpty()) {
+                               CompositePathObject path = this.getValidCompositePath(objects);
+                               while (path != null) {
+                                       this.paths.add(path);
+                                       if (objects.isEmpty())
+                                               break;
+                                       path = this.getValidCompositePath(objects);
+                               }
+                       }
+
+                       if (!this.requestRejected) {
+                               this.msgs.add(new PCEPReplyMessage(Collections.unmodifiableList(Arrays.asList(new CompositeResponseObject(rpObj, this.noPath, this.lsp,
+                                               this.lspa, this.bandwidth, this.metrics, this.iro, this.paths))), Collections.unmodifiableList(svecList)));
+                       }
+
+                       return this.msgs;
+               }
+
+               private CompositePathObject getValidCompositePath(List<PCEPObject> objects) {
+                       if (!(objects.get(0) instanceof PCEPExplicitRouteObject))
+                               return null;
+
+                       final PCEPExplicitRouteObject explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+                       objects.remove(0);
+
+                       PCEPLspaObject pathLspa = null;
+                       PCEPRequestedPathBandwidthObject pathBandwidth = null;
+                       final List<PCEPMetricObject> pathMetrics = new ArrayList<PCEPMetricObject>();
+                       PCEPIncludeRouteObject pathIro = null;
+
+                       PCEPObject obj;
+                       int state = 1;
+                       while (!objects.isEmpty()) {
+                               obj = objects.get(0);
+                               if (obj instanceof UnknownObject) {
+                                       if (((UnknownObject) obj).isProcessed()) {
+                                               this.msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(this.rpObj, false), new PCEPErrorObject(((UnknownObject) obj)
+                                                               .getError()))));
+                                               this.requestRejected = true;
+                                       }
+                                       objects.remove(0);
+                                       continue;
+                               }
+
+                               switch (state) {
+                                       case 1:
+                                               state = 2;
+                                               if (obj instanceof PCEPLspaObject) {
+                                                       pathLspa = (PCEPLspaObject) obj;
+                                                       break;
+                                               }
+                                       case 2:
+                                               state = 3;
+                                               if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                                                       pathBandwidth = (PCEPRequestedPathBandwidthObject) obj;
+                                                       break;
+                                               }
+                                       case 3:
+                                               state = 4;
+                                               if (obj instanceof PCEPMetricObject) {
+                                                       pathMetrics.add((PCEPMetricObject) obj);
+                                                       state = 3;
+                                                       break;
+                                               }
+                                       case 4:
+                                               state = 5;
+                                               if (obj instanceof PCEPIncludeRouteObject) {
+                                                       pathIro = (PCEPIncludeRouteObject) obj;
+                                                       state = 6;
+                                                       break;
+                                               }
+
+                               }
+
+                               if (state == 5)
+                                       break;
+
+                               objects.remove(0);
+
+                               if (state == 6)
+                                       break;
+                       }
+
+                       return new CompositePathObject(explicitRoute, pathLspa, pathBandwidth, pathMetrics, pathIro);
+               }
+       }
+
+       @Override
+       public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+               if (objects == null)
+                       throw new IllegalArgumentException("Passed list can't be null.");
+
+               final List<PCEPMessage> msgs = new ArrayList<PCEPMessage>();
+               final List<CompositeReplySvecObject> svecList = new ArrayList<CompositeReplySvecObject>();
+
+               CompositeReplySvecObject svecComp;
+               while (!objects.isEmpty()) {
+                       try {
+                               if ((svecComp = this.getValidSvecComposite(objects)) == null)
+                                       break;
+                       } catch (final PCEPDocumentedException e) {
+                               msgs.add(new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+                               return msgs;
+                       }
+
+                       svecList.add(svecComp);
+               }
+
+               List<PCEPMessage> subMessages;
+               final SubReplyValidator subValidator = new SubReplyValidator();
+               while (!objects.isEmpty()) {
+                       subMessages = subValidator.validate(objects, svecList);
+                       if (subMessages == null)
+                               break;
+                       msgs.addAll(subMessages);
+               }
+
+               if (msgs.isEmpty()) {
+                       msgs.add(new PCEPErrorMessage(new PCEPErrorObject(PCEPErrors.RP_MISSING)));
+                       return msgs;
+               }
+
+               if (!objects.isEmpty())
+                       throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+               return msgs;
+       }
+
+       private CompositeReplySvecObject getValidSvecComposite(List<PCEPObject> objects) throws PCEPDocumentedException {
+               if (objects == null)
+                       throw new IllegalArgumentException("List cannot be null.");
+
+               if (!(objects.get(0) instanceof PCEPSvecObject))
+                       return null;
+
+               final PCEPSvecObject svec = (PCEPSvecObject) objects.get(0);
+               objects.remove(0);
+
+               PCEPObjectiveFunctionObject of = null;
+               final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+               PCEPObject obj;
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       obj = objects.get(0);
+
+                       if (obj instanceof UnknownObject)
+                               throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPObjectiveFunctionObject) {
+                                               of = (PCEPObjectiveFunctionObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPMetricObject) {
+                                               metrics.add((PCEPMetricObject) obj);
+                                               state = 2;
+                                               break;
+                                       }
+                       }
+
+                       if (state == 3)
+                               break;
+
+                       objects.remove(0);
+               }
+
+               return new CompositeReplySvecObject(svec, of, metrics);
+       }
+
+       private static PCEPRequestParameterObject copyRP(PCEPRequestParameterObject origRp, boolean processed) {
+               return new PCEPRequestParameterObject(origRp.isLoose(), origRp.isBidirectional(), origRp.isReoptimized(), origRp.isMakeBeforeBreak(),
+                               origRp.isReportRequestOrder(), origRp.isSuplyOFOnResponse(), origRp.isFragmentation(), origRp.isP2mp(), origRp.isEroCompression(),
+                               origRp.getPriority(), origRp.getRequestID(), origRp.getTlvs(), processed, origRp.isIgnored());
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReportMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReportMessageParser.java
new file mode 100644 (file)
index 0000000..e4128f6
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPReportMessage
+ * PCEPReportMessage}
+ */
+public class PCEPReportMessageParser implements PCEPMessageParser {
+
+       @Override
+       public byte[] put(PCEPMessage msg) {
+               if (!(msg instanceof PCEPReportMessage))
+                       throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPReportMessage.");
+
+               return PCEPObjectFactory.put(((PCEPReportMessage) msg).getAllObjects());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReportMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPReportMessageValidator.java
new file mode 100644 (file)
index 0000000..a9b06b4
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
+import org.opendaylight.protocol.pcep.object.CompositeRptPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+
+/**
+ * PCEPReportMessage validator. Validates message integrity.
+ */
+public class PCEPReportMessageValidator extends PCEPMessageValidator {
+
+       @Override
+       public List<PCEPMessage> validate(final List<PCEPObject> objects) throws PCEPDeserializerException {
+               if (objects == null)
+                       throw new IllegalArgumentException("Passed list can't be null.");
+
+               final List<CompositeStateReportObject> report = new ArrayList<CompositeStateReportObject>();
+
+               while (!objects.isEmpty()) {
+                       if (objects.get(0) instanceof UnknownObject)
+                               return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(((UnknownObject) objects.get(0)).getError())));
+
+                       if (!(objects.get(0) instanceof PCEPLspObject))
+                               return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(PCEPErrors.LSP_MISSING)));
+
+                       final PCEPLspObject lsp = (PCEPLspObject) objects.get(0);
+                       objects.remove(0);
+
+                       final List<CompositeRptPathObject> paths = new ArrayList<CompositeRptPathObject>();
+
+                       if (!objects.isEmpty()) {
+                               try {
+                                       CompositeRptPathObject path;
+                                       path = this.getValidCompositePath(objects);
+                                       while (path != null) {
+                                               paths.add(path);
+                                               if (objects.isEmpty())
+                                                       break;
+                                               path = this.getValidCompositePath(objects);
+                                       }
+                               } catch (final PCEPDocumentedException e) {
+                                       return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+                               }
+                       }
+
+                       report.add(new CompositeStateReportObject(lsp, paths));
+               }
+
+               if (report.isEmpty())
+                       throw new PCEPDeserializerException("Atleast one CompositeStateReportObject is mandatory.");
+
+               if (!objects.isEmpty()) {
+                       if (objects.get(0) instanceof UnknownObject)
+                               return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(((UnknownObject) objects.get(0)).getError())));
+                       throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+               }
+
+               return Arrays.asList((PCEPMessage) new PCEPReportMessage(report));
+       }
+
+       private CompositeRptPathObject getValidCompositePath(final List<PCEPObject> objects) throws PCEPDocumentedException {
+               if (objects.get(0) instanceof UnknownObject)
+                       throw new PCEPDocumentedException("Unknown object", ((UnknownObject) objects.get(0)).getError());
+               if (!(objects.get(0) instanceof PCEPExplicitRouteObject))
+                       return null;
+               final PCEPExplicitRouteObject explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+               objects.remove(0);
+
+               PCEPLspaObject pathLspa = null;
+               PCEPExistingPathBandwidthObject pathBandwidth = null;
+               PCEPReportedRouteObject pathRro = null;
+               final List<PCEPMetricObject> pathMetrics = new ArrayList<PCEPMetricObject>();
+
+               PCEPObject obj;
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       obj = objects.get(0);
+                       if (obj instanceof UnknownObject) {
+                               throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+                       }
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPLspaObject) {
+                                               pathLspa = (PCEPLspaObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPExistingPathBandwidthObject) {
+                                               pathBandwidth = (PCEPExistingPathBandwidthObject) obj;
+                                               break;
+                                       }
+
+                               case 3:
+                                       state = 4;
+                                       if (obj instanceof PCEPReportedRouteObject) {
+                                               pathRro = (PCEPReportedRouteObject) obj;
+                                               break;
+                                       }
+                               case 4:
+                                       state = 5;
+                                       if (obj instanceof PCEPMetricObject) {
+                                               pathMetrics.add((PCEPMetricObject) obj);
+                                               state = 4;
+                                               break;
+                                       }
+                       }
+
+                       if (state == 5)
+                               break;
+
+                       objects.remove(0);
+               }
+
+               return new CompositeRptPathObject(explicitRoute, pathLspa, pathBandwidth, pathRro, pathMetrics);
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPRequestMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPRequestMessageParser.java
new file mode 100644 (file)
index 0000000..2bf9dab
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPReportMessage
+ * PCEPReportMessage}
+ */
+public class PCEPRequestMessageParser implements PCEPMessageParser {
+
+       @Override
+       public byte[] put(PCEPMessage msg) {
+               if (!(msg instanceof PCEPRequestMessage))
+                       throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Needed PCEPRequestMessage.");
+
+               return PCEPObjectFactory.put(((PCEPRequestMessage) msg).getAllObjects());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPRequestMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPRequestMessageValidator.java
new file mode 100644 (file)
index 0000000..4e7e43a
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestSvecObject;
+import org.opendaylight.protocol.pcep.object.PCEPClassTypeObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+
+/**
+ * PCEPRequestMessage validator. Validates message integrity.
+ */
+public class PCEPRequestMessageValidator extends PCEPMessageValidator {
+
+       @Override
+       public List<PCEPMessage> validate(List<PCEPObject> objects) {
+               if (objects == null)
+                       throw new IllegalArgumentException("Passed list can't be null.");
+
+               final List<PCEPMessage> msgs = new ArrayList<PCEPMessage>();
+               final List<CompositeRequestSvecObject> svecList = new ArrayList<CompositeRequestSvecObject>();
+
+               CompositeRequestSvecObject svecComp;
+               while (!objects.isEmpty()) {
+                       try {
+                               if ((svecComp = getValidSvecComposite(objects)) == null)
+                                       break;
+                       } catch (final PCEPDocumentedException e) {
+                               msgs.add(new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+                               return msgs;
+                       }
+
+                       svecList.add(svecComp);
+               }
+
+               while (!objects.isEmpty()) {
+                       final List<CompositeRequestObject> requests = new ArrayList<CompositeRequestObject>();
+                       PCEPRequestParameterObject rpObj = null;
+                       boolean requestRejected = false;
+
+                       if (objects.get(0) instanceof PCEPRequestParameterObject) {
+                               rpObj = (PCEPRequestParameterObject) objects.get(0);
+                               objects.remove(rpObj);
+                               if (!rpObj.isProcessed()) {
+                                       msgs.add(new PCEPErrorMessage(new CompositeErrorObject(rpObj, new PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))));
+                                       requestRejected = true;
+                               }
+
+                       } else {
+                               // if RP obj is missing return error only;
+                               msgs.clear();
+                               msgs.add(new PCEPErrorMessage(new PCEPErrorObject(PCEPErrors.RP_MISSING)));
+                               return msgs;
+                       }
+
+                       PCEPEndPointsObject<?> endPoints = null;
+                       if (objects.get(0) instanceof PCEPEndPointsObject<?>) {
+                               endPoints = (PCEPEndPointsObject<?>) objects.get(0);
+                               objects.remove(0);
+                               if (!endPoints.isProcessed()) {
+                                       msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))));
+                                       requestRejected = true;
+                               }
+                       } else {
+                               msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(PCEPErrors.END_POINTS_MISSING))));
+                               requestRejected = true;
+                       }
+
+                       // ignore all continual end-points objects
+                       while (!objects.isEmpty() && objects.get(0) instanceof PCEPEndPointsObject<?>) {
+                               objects.remove(0);
+                       }
+
+                       PCEPClassTypeObject classType = null;
+                       PCEPLspObject lsp = null;
+                       PCEPLspaObject lspa = null;
+                       PCEPRequestedPathBandwidthObject bandwidth = null;
+                       final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+                       PCEPReportedRouteObject rro = null;
+                       PCEPExistingPathBandwidthObject rroBandwidth = null;
+                       PCEPIncludeRouteObject iro = null;
+                       PCEPLoadBalancingObject loadBalancing = null;
+
+                       int state = 1;
+                       while (!objects.isEmpty()) {
+                               final PCEPObject obj = objects.get(0);
+                               if (obj instanceof UnknownObject) {
+                                       if (((UnknownObject) obj).isProcessed()) {
+                                               msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(((UnknownObject) obj).getError()))));
+                                               requestRejected = true;
+                                       }
+
+                                       objects.remove(0);
+                                       continue;
+                               }
+                               switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPClassTypeObject) {
+                                               classType = (PCEPClassTypeObject) obj;
+                                               if (!classType.isProcessed()) {
+                                                       msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))));
+                                                       requestRejected = true;
+                                               }
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPLspObject) {
+                                               lsp = (PCEPLspObject) obj;
+                                               break;
+                                       }
+                               case 3:
+                                       state = 4;
+                                       if (obj instanceof PCEPLspaObject) {
+                                               lspa = (PCEPLspaObject) obj;
+                                               break;
+                                       }
+                               case 4:
+                                       state = 5;
+                                       if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                                               bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+                                               break;
+                                       }
+                               case 5:
+                                       state = 6;
+                                       if (obj instanceof PCEPMetricObject) {
+                                               metrics.add((PCEPMetricObject) obj);
+                                               state = 5;
+
+                                               break;
+                                       }
+                               case 6:
+                                       state = 8;
+                                       if (obj instanceof PCEPReportedRouteObject) {
+                                               rro = (PCEPReportedRouteObject) obj;
+                                               state = 7;
+                                               break;
+                                       }
+                               case 7:
+                                       state = 8;
+                                       if (obj instanceof PCEPExistingPathBandwidthObject) {
+                                               rroBandwidth = (PCEPExistingPathBandwidthObject) obj;
+                                               break;
+                                       }
+                               case 8:
+                                       state = 9;
+                                       if (obj instanceof PCEPIncludeRouteObject) {
+                                               iro = (PCEPIncludeRouteObject) obj;
+                                               break;
+                                       }
+                               case 9:
+                                       if (obj instanceof PCEPLoadBalancingObject) {
+                                               loadBalancing = (PCEPLoadBalancingObject) obj;
+                                               break;
+                                       }
+                                       state = 10;
+                               }
+
+                               if (state == 10) {
+                                       break;
+                               }
+
+                               objects.remove(obj);
+                       }
+
+                       if (rpObj.isReoptimized() && bandwidth != null && bandwidth.getBandwidth().compareTo(new Bandwidth(0)) > 0 && rro == null) {
+                               msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(PCEPErrors.RRO_MISSING))));
+                               requestRejected = true;
+                       }
+
+                       if (!requestRejected) {
+                               requests.add(new CompositeRequestObject(rpObj, endPoints, classType, lsp, lspa, bandwidth, metrics, rro, rroBandwidth, iro, loadBalancing));
+                               msgs.add(new PCEPRequestMessage(Collections.unmodifiableList(svecList), Collections.unmodifiableList(requests)));
+                       }
+               }
+
+               return msgs;
+       }
+
+       private static CompositeRequestSvecObject getValidSvecComposite(List<PCEPObject> objects) throws PCEPDocumentedException {
+               if (objects == null || objects.isEmpty()) {
+                       throw new IllegalArgumentException("List cannot be null or empty.");
+               }
+
+               PCEPSvecObject svec = null;
+               if (objects.get(0) instanceof PCEPSvecObject) {
+                       svec = (PCEPSvecObject) objects.get(0);
+                       objects.remove(svec);
+               } else
+                       return null;
+
+               PCEPObjectiveFunctionObject of = null;
+               PCEPGlobalConstraintsObject gc = null;
+               PCEPExcludeRouteObject xro = null;
+               final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       final PCEPObject obj = objects.get(0);
+
+                       if (obj instanceof UnknownObject && ((UnknownObject) obj).isProcessed()) {
+                               throw new PCEPDocumentedException("Unknown object in SVEC list.", ((UnknownObject) obj).getError());
+                       }
+
+                       switch (state) {
+                       case 1:
+                               state = 2;
+                               if (obj instanceof PCEPObjectiveFunctionObject) {
+                                       of = (PCEPObjectiveFunctionObject) obj;
+                                       break;
+                               }
+                       case 2:
+                               state = 3;
+                               if (obj instanceof PCEPGlobalConstraintsObject) {
+                                       gc = (PCEPGlobalConstraintsObject) obj;
+                                       break;
+                               }
+                       case 3:
+                               state = 4;
+                               if (obj instanceof PCEPExcludeRouteObject) {
+                                       xro = (PCEPExcludeRouteObject) obj;
+                                       break;
+                               }
+                       case 4:
+                               state = 5;
+                               if (obj instanceof PCEPMetricObject) {
+                                       metrics.add((PCEPMetricObject) obj);
+                                       state = 4;
+
+                                       break;
+                               }
+                       }
+
+                       if (state == 5)
+                               break;
+
+                       objects.remove(obj);
+               }
+
+               return new CompositeRequestSvecObject(svec, of, gc, xro, metrics);
+       }
+
+       private static PCEPRequestParameterObject copyRP(PCEPRequestParameterObject origRp, boolean processed) {
+               return new PCEPRequestParameterObject(origRp.isLoose(), origRp.isBidirectional(), origRp.isReoptimized(), origRp.isMakeBeforeBreak(),
+                               origRp.isReportRequestOrder(), origRp.isSuplyOFOnResponse(), origRp.isFragmentation(), origRp.isP2mp(), origRp.isEroCompression(),
+                               origRp.getPriority(), origRp.getRequestID(), origRp.getTlvs(), processed, origRp.isIgnored());
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPUpdateRequestMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPUpdateRequestMessageParser.java
new file mode 100644 (file)
index 0000000..002f48a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
+
+public class PCEPUpdateRequestMessageParser implements PCEPMessageParser {
+       @Override
+       public byte[] put(PCEPMessage msg) {
+               if (!(msg instanceof PCEPUpdateRequestMessage))
+                       throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPUpdateRequestMessage.");
+
+               return PCEPObjectFactory.put(((PCEPUpdateRequestMessage) msg).getAllObjects());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPUpdateRequestMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPUpdateRequestMessageValidator.java
new file mode 100644 (file)
index 0000000..64497b1
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
+import org.opendaylight.protocol.pcep.object.CompositeUpdPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+
+/**
+ * PCEPUpdateRequestMessage validator. Validates message integrity.
+ */
+public class PCEPUpdateRequestMessageValidator extends PCEPMessageValidator {
+
+       private static final Logger logger = LoggerFactory.getLogger(PCEPUpdateRequestMessageValidator.class);
+
+       @Override
+       public List<PCEPMessage> validate(final List<PCEPObject> objects) throws PCEPDeserializerException {
+               if (objects == null)
+                       throw new IllegalArgumentException("Passed list can't be null.");
+
+               final List<CompositeUpdateRequestObject> updateRequests = new ArrayList<CompositeUpdateRequestObject>();
+
+               while (!objects.isEmpty()) {
+                       if (objects.get(0) instanceof UnknownObject) {
+                               logger.warn("Unknown object found (should be Lsp) - {}.", objects.get(0));
+                               return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(((UnknownObject) objects.get(0)).getError())));
+                       }
+                       if (!(objects.get(0) instanceof PCEPLspObject))
+                               return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(PCEPErrors.LSP_MISSING)));
+
+                       final PCEPLspObject lsp = (PCEPLspObject) objects.get(0);
+                       objects.remove(0);
+
+                       final List<CompositeUpdPathObject> paths = new ArrayList<CompositeUpdPathObject>();
+
+                       if (!objects.isEmpty()) {
+                               try {
+                                       CompositeUpdPathObject path;
+                                       path = this.getValidCompositePath(objects);
+                                       while (path != null) {
+                                               paths.add(path);
+                                               if (objects.isEmpty())
+                                                       break;
+                                               path = this.getValidCompositePath(objects);
+                                       }
+                               } catch (final PCEPDocumentedException e) {
+                                       logger.warn("Serializing failed: {}.", e);
+                                       return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+                               }
+                       }
+
+                       updateRequests.add(new CompositeUpdateRequestObject(lsp, paths));
+               }
+
+               if (updateRequests.isEmpty())
+                       return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(PCEPErrors.LSP_MISSING)));
+
+               if (!objects.isEmpty())
+                       throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+               return Arrays.asList((PCEPMessage) new PCEPUpdateRequestMessage(updateRequests));
+       }
+
+       private CompositeUpdPathObject getValidCompositePath(final List<PCEPObject> objects) throws PCEPDocumentedException {
+               if (!(objects.get(0) instanceof PCEPExplicitRouteObject))
+                       return null;
+
+               if (objects.get(0) instanceof UnknownObject)
+                       throw new PCEPDocumentedException("Unknown object", ((UnknownObject) objects.get(0)).getError());
+               final PCEPExplicitRouteObject explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+               objects.remove(0);
+
+               PCEPLspaObject pathLspa = null;
+               PCEPRequestedPathBandwidthObject pathBandwidth = null;
+               final List<PCEPMetricObject> pathMetrics = new ArrayList<PCEPMetricObject>();
+
+               PCEPObject obj;
+               int state = 1;
+               while (!objects.isEmpty()) {
+                       obj = objects.get(0);
+                       if (obj instanceof UnknownObject) {
+                               throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+                       }
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPLspaObject) {
+                                               pathLspa = (PCEPLspaObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       if (obj instanceof PCEPRequestedPathBandwidthObject) {
+                                               pathBandwidth = (PCEPRequestedPathBandwidthObject) obj;
+                                               break;
+                                       }
+                               case 3:
+                                       state = 4;
+                                       if (obj instanceof PCEPMetricObject) {
+                                               pathMetrics.add((PCEPMetricObject) obj);
+                                               state = 3;
+                                               break;
+                                       }
+                       }
+
+                       if (state == 4)
+                               break;
+
+                       objects.remove(0);
+               }
+
+               return new CompositeUpdPathObject(explicitRoute, pathLspa, pathBandwidth, pathMetrics);
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRAddTunnelMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRAddTunnelMessageParser.java
new file mode 100644 (file)
index 0000000..4a33f1a
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPXRAddTunnelMessage;
+
+/**
+ * Parser for {@link #PCEPXRAddTunnelMessage} PCEPXRAddTunnelMessage
+ */
+public class PCEPXRAddTunnelMessageParser implements PCEPMessageParser {
+
+       @Override
+       public byte[] put(PCEPMessage msg) {
+               if (!(msg instanceof PCEPXRAddTunnelMessage))
+                       throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPXRAddTunnelMessage.");
+
+               return PCEPObjectFactory.put(((PCEPXRAddTunnelMessage) msg).getAllObjects());
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRAddTunnelMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRAddTunnelMessageValidator.java
new file mode 100644 (file)
index 0000000..9e05bef
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPXRAddTunnelMessage;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+
+/**
+ * PCEPXRAddTunnelMessage validator. Validates message integrity.
+ */
+public class PCEPXRAddTunnelMessageValidator extends PCEPMessageValidator {
+
+       @Override
+       public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+               if (objects == null)
+                       throw new IllegalArgumentException("Passed list can't be null.");
+
+               PCEPObject obj;
+               int state = 1;
+
+               PCEPLspObject lsp = null;
+               PCEPEndPointsObject<?> ends = null;
+               PCEPExplicitRouteObject ero = null;
+
+               while (!objects.isEmpty()) {
+                       obj = objects.get(0);
+                       if (obj instanceof UnknownObject) {
+                               return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(((UnknownObject) obj).getError())));
+                       }
+
+                       switch (state) {
+                               case 1:
+                                       state = 2;
+                                       if (obj instanceof PCEPLspObject) {
+                                               lsp = (PCEPLspObject) obj;
+                                               break;
+                                       }
+                               case 2:
+                                       state = 3;
+                                       //FIXME: add support for ipv6?
+                                       if (obj instanceof PCEPEndPointsObject<?>) {
+                                               ends = ((PCEPEndPointsObject<?>) obj);
+                                               break;
+                                       }
+                               case 3:
+                                       state = 4;
+                                       if (obj instanceof PCEPExplicitRouteObject) {
+                                               ero = (PCEPExplicitRouteObject) obj;
+                                               break;
+                                       }
+                       }
+
+                       objects.remove(0);
+
+                       if (state == 4)
+                               break;
+               }
+               if (lsp == null || ends == null || ero == null) {
+                       throw new PCEPDeserializerException("All objects are mandatory.");
+               }
+
+               if (!objects.isEmpty())
+                       throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+               PCEPXRAddTunnelMessage msg = null;
+
+               if (ends.getSourceAddress() instanceof IPv4Address && ends.getDestinationAddress() instanceof IPv4Address) {
+                       /*
+                        * The generic type is checked above.
+                        */
+                       @SuppressWarnings("unchecked")
+                       final PCEPEndPointsObject<IPv4Address> ep = (PCEPEndPointsObject<IPv4Address>) ends;
+                       msg = new PCEPXRAddTunnelMessage(lsp, ep, ero);
+               }
+               return Arrays.asList((PCEPMessage) msg);
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRDeleteTunnelMessageParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRDeleteTunnelMessageParser.java
new file mode 100644 (file)
index 0000000..9822d7a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPXRDeleteTunnelMessage;
+
+public class PCEPXRDeleteTunnelMessageParser implements PCEPMessageParser {
+
+       @Override
+       public byte[] put(PCEPMessage msg) {
+               if (!(msg instanceof PCEPXRDeleteTunnelMessage))
+                       throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPXRDeleteTunnelMessage.");
+
+               return PCEPObjectFactory.put(((PCEPXRDeleteTunnelMessage) msg).getAllObjects());
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRDeleteTunnelMessageValidator.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/message/PCEPXRDeleteTunnelMessageValidator.java
new file mode 100644 (file)
index 0000000..6d41734
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.message;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.message.PCEPXRDeleteTunnelMessage;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+
+/**
+ * PCEPXRDeleteTunnelMessage validator. Validates message integrity.
+ */
+public class PCEPXRDeleteTunnelMessageValidator extends PCEPMessageValidator {
+
+       @Override
+       public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+               if (objects == null || objects.isEmpty())
+                       throw new IllegalArgumentException("Passed list can't be null or empty.");
+
+               PCEPObject obj;
+
+               //PCEPRequestParameterObject rp = null;
+               PCEPLspObject lsp = null;
+               //      PCEPNoPathObject noPath = null;
+
+               obj = objects.get(0);
+
+               if (obj instanceof PCEPLspObject) {
+                       lsp = (PCEPLspObject) obj;
+               }
+
+               if (lsp == null) {
+                       throw new PCEPDeserializerException("All objects are mandatory.");
+               }
+
+               return Arrays.asList((PCEPMessage) new PCEPXRDeleteTunnelMessage(lsp));
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPBranchNodeListObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPBranchNodeListObjectParser.java
new file mode 100644 (file)
index 0000000..2a57219
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPEROSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPBranchNodeListObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+public class PCEPBranchNodeListObjectParser implements PCEPObjectParser {
+
+       @Override
+       public PCEPBranchNodeListObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+               final List<ExplicitRouteSubobject> subobjects = PCEPEROSubobjectParser.parse(bytes);
+               if (subobjects.isEmpty())
+                       throw new PCEPDeserializerException("Empty Branch Node List Object.");
+
+               return new PCEPBranchNodeListObject(subobjects, processed, ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPBranchNodeListObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPBranchNodeListObject.");
+
+               assert !(((PCEPBranchNodeListObject) obj).getSubobjects().isEmpty()) : "Empty Branch Node List Object.";
+
+               return PCEPEROSubobjectParser.put(((PCEPBranchNodeListObject) obj).getSubobjects());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPClassTypeObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPClassTypeObjectParser.java
new file mode 100644 (file)
index 0000000..5ffcea9
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPClassTypeObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPClassTypeObject PCEPClassTypeObject}
+ */
+public class PCEPClassTypeObjectParser implements PCEPObjectParser {
+
+       /**
+        * Length of Class Type field in bits.
+        */
+       public static final int CT_F_LENGTH = 3;
+
+       /**
+        * Reserved field bit length.
+        */
+       public static final int RESERVED = 29;
+
+       /**
+        * Size of the object in bytes.
+        */
+       public static final int SIZE = (RESERVED + CT_F_LENGTH) / 8;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored)
+                       throws PCEPDeserializerException, PCEPDocumentedException {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Byte array is mandatory.");
+               if (bytes.length != SIZE)
+                       throw new PCEPDeserializerException("Size of byte array doesn't match defined size. Expected: " + SIZE + "; Passed: " + bytes.length);
+               if (!processed)
+                       throw new PCEPDocumentedException("Processed bit not set", PCEPErrors.P_FLAG_NOT_SET);
+               final short classType = (short) (bytes[SIZE-1] & 0xFF);
+               if (classType < 0 || classType > 8) {
+                       throw new PCEPDocumentedException("Invalid class type " + classType, PCEPErrors.INVALID_CT);
+               }
+               return new PCEPClassTypeObject(classType);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPClassTypeObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPClassTypeObject.");
+
+               final byte[] retBytes = new byte[SIZE];
+               retBytes[SIZE-1] = ByteArray.shortToBytes(((PCEPClassTypeObject) obj).getClassType())[1];
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPCloseObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPCloseObjectParser.java
new file mode 100644 (file)
index 0000000..8676d25
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPCloseObject PCEPCloseObject}
+ */
+public class PCEPCloseObjectParser implements PCEPObjectParser {
+
+       /*
+        * lengths of fields in bytes
+        */
+       public static final int FLAGS_F_LENGTH = 1;
+       public static final int REASON_F_LENGTH = 1;
+
+       /*
+        * offsets of fields in bytes
+        */
+       public static final int FLAGS_F_OFFSET = 2; // added reserved field of size 2 bytes
+       public static final int REASON_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+
+       /*
+        * total size of object in bytes
+        */
+       public static final int TLVS_F_OFFSET = REASON_F_OFFSET + REASON_F_LENGTH;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Byte array is mandatory.");
+
+               if (bytes.length != TLVS_F_OFFSET)
+                       throw new PCEPDeserializerException("Size of byte array doesn't match defined size. Expected: " + TLVS_F_OFFSET + "; Passed: " + bytes.length);
+
+               Reason reason;
+               switch ((short) (bytes[REASON_F_OFFSET] & 0xFF)) {
+                       case 1:
+                               reason = Reason.UNKNOWN;
+                               break;
+                       case 2:
+                               reason = Reason.EXP_DEADTIMER;
+                               break;
+                       case 3:
+                               reason = Reason.MALFORMED_MSG;
+                               break;
+                       case 4:
+                               reason = Reason.TOO_MANY_UNKNOWN_REQ_REP;
+                               break;
+                       case 5:
+                               reason = Reason.TOO_MANY_UNKNOWN_MSG;
+                               break;
+                       default:
+                               reason = Reason.UNKNOWN;
+                               break;
+               }
+
+               return new PCEPCloseObject(reason, PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_F_OFFSET)));
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPCloseObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPCloseObject.");
+
+               final byte[] tlvs = PCEPTlvParser.put(((PCEPCloseObject) obj).getTlvs());
+               final byte[] retBytes = new byte[TLVS_F_OFFSET + tlvs.length];
+               ByteArray.copyWhole(tlvs, retBytes, TLVS_F_OFFSET);
+
+               int reason;
+               switch (((PCEPCloseObject) obj).getReason()) {
+                       case UNKNOWN:
+                               reason = 1;
+                               break;
+                       case EXP_DEADTIMER:
+                               reason = 2;
+                               break;
+                       case MALFORMED_MSG:
+                               reason = 3;
+                               break;
+                       case TOO_MANY_UNKNOWN_REQ_REP:
+                               reason = 4;
+                               break;
+                       case TOO_MANY_UNKNOWN_MSG:
+                               reason = 5;
+                               break;
+                       default:
+                               reason = 1;
+                               break;
+               }
+
+               retBytes[REASON_F_OFFSET] = (byte) reason;
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPEndPointsIPv4ObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPEndPointsIPv4ObjectParser.java
new file mode 100644 (file)
index 0000000..4beaa2b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for IPv4 {@link org.opendaylight.protocol.pcep.object.PCEPEndPointsObject
+ * PCEPEndPointsObject}
+ */
+public class PCEPEndPointsIPv4ObjectParser implements PCEPObjectParser {
+
+       /*
+        * fields lengths and offsets for IPv4 in bytes
+        */
+       public static final int SRC4_F_LENGTH = 4;
+       public static final int DEST4_F_LENGTH = 4;
+
+       public static final int SRC4_F_OFFSET = 0;
+       public static final int DEST4_F_OFFSET = SRC4_F_OFFSET + SRC4_F_LENGTH;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Array of bytes is mandatory");
+               if (bytes.length != SRC4_F_LENGTH + DEST4_F_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes.");
+
+               //FIXME: create new constructor which allows processed parameter - needed for validation
+               return new PCEPEndPointsObject<IPv4Address>(
+                               new IPv4Address(ByteArray.subByte(bytes, SRC4_F_OFFSET, SRC4_F_LENGTH)),
+                               new IPv4Address(ByteArray.subByte(bytes, DEST4_F_OFFSET, DEST4_F_LENGTH)));
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPEndPointsObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPEndPointsObject.");
+
+               final PCEPEndPointsObject<?> ePObj = (PCEPEndPointsObject<?>) obj;
+
+               if (!(ePObj.getSourceAddress() instanceof IPv4Address))
+                       throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + ePObj.getSourceAddress().getClass() + ". Needed IPv4Address");
+
+               final byte[] retBytes = new byte[SRC4_F_LENGTH + DEST4_F_LENGTH];
+               ByteArray.copyWhole(((IPv4Address) ePObj.getSourceAddress()).getAddress(), retBytes, SRC4_F_OFFSET);
+               ByteArray.copyWhole(((IPv4Address) ePObj.getDestinationAddress()).getAddress(), retBytes, DEST4_F_OFFSET);
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPEndPointsIPv6ObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPEndPointsIPv6ObjectParser.java
new file mode 100644 (file)
index 0000000..2be773f
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for IPv6 {@link org.opendaylight.protocol.pcep.object.PCEPEndPointsObject
+ * PCEPEndPointsObject}
+ */
+public class PCEPEndPointsIPv6ObjectParser implements PCEPObjectParser {
+
+       public static final int SRC6_F_LENGTH = 16;
+       public static final int DEST6_F_LENGT = 16;
+
+       public static final int SRC6_F_OFFSET = 0;
+       public static final int DEST6_F_OFFSET = SRC6_F_OFFSET + SRC6_F_LENGTH;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Array of bytes is mandatory");
+               if (bytes.length != SRC6_F_LENGTH + DEST6_F_LENGT)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes.");
+
+               if (!processed)
+                       throw new PCEPDocumentedException("Processed flag not set", PCEPErrors.P_FLAG_NOT_SET);
+
+               return new PCEPEndPointsObject<IPv6Address>(
+                               new IPv6Address(ByteArray.subByte(bytes, SRC6_F_OFFSET, SRC6_F_LENGTH)),
+                               new IPv6Address(ByteArray.subByte(bytes, DEST6_F_OFFSET, DEST6_F_LENGT)));
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPEndPointsObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPEndPointsObject.");
+
+               final PCEPEndPointsObject<?> ePObj = (PCEPEndPointsObject<?>) obj;
+
+               if (!(ePObj.getSourceAddress() instanceof IPv6Address))
+                       throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + ePObj.getSourceAddress().getClass() + ". Needed IPv6Address");
+
+               final byte[] retBytes = new byte[SRC6_F_LENGTH + DEST6_F_LENGT];
+               ByteArray.copyWhole(((IPv6Address) ePObj.getSourceAddress()).getAddress(), retBytes, SRC6_F_OFFSET);
+               ByteArray.copyWhole(((IPv6Address) ePObj.getDestinationAddress()).getAddress(), retBytes, DEST6_F_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPErrorObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPErrorObjectParser.java
new file mode 100644 (file)
index 0000000..64f850f
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPErrorObject PCEPErrorObject}
+ */
+public class PCEPErrorObjectParser implements PCEPObjectParser {
+       /**
+        * Caret for combination of Error-type and Error-value
+        */
+       public static class PCEPErrorIdentifier {
+               public final short type;
+               public final short value;
+
+               private PCEPErrorIdentifier(final short type, final short value) {
+                       this.type = type;
+                       this.value = value;
+               }
+
+               @Override
+               public int hashCode() {
+                       final int prime = 31;
+                       int result = 1;
+                       result = prime * result + this.type;
+                       result = prime * result + this.value;
+                       return result;
+               }
+
+               @Override
+               public boolean equals(final Object obj) {
+                       if (this == obj)
+                               return true;
+                       if (obj == null)
+                               return false;
+                       if (this.getClass() != obj.getClass())
+                               return false;
+                       final PCEPErrorIdentifier other = (PCEPErrorIdentifier) obj;
+                       if (this.type != other.type)
+                               return false;
+                       if (this.value != other.value)
+                               return false;
+                       return true;
+               }
+
+               @Override
+               public String toString() {
+                       return "type " + this.type + " value " + this.value;
+               }
+       }
+
+       /**
+        * Bidirectional mapping of {@link org.opendaylight.protocol.pcep.PCEPErrors PCEPErrors}
+        * and
+        * {@link org.opendaylight.protocol.pcep.impl.object.PCEPErrorObjectParser.PCEPErrorIdentifier
+        * ErrorIdentifier}
+        */
+       public static class PCEPErrorsMaping {
+               private static final PCEPErrorsMaping instance = new PCEPErrorsMaping();
+
+               private final Map<PCEPErrors, PCEPErrorIdentifier> errorsMap = new HashMap<PCEPErrors, PCEPErrorIdentifier>();
+               private final Map<PCEPErrorIdentifier, PCEPErrors> errorIdsMap = new HashMap<PCEPErrorIdentifier, PCEPErrors>();
+
+               private PCEPErrorsMaping() {
+                       this.fillIn();
+               }
+
+               private void fillIn() {
+                       this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 1), PCEPErrors.NON_OR_INVALID_OPEN_MSG);
+                       this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 2), PCEPErrors.NO_OPEN_BEFORE_EXP_OPENWAIT);
+                       this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 3), PCEPErrors.NON_ACC_NON_NEG_SESSION_CHAR);
+                       this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 4), PCEPErrors.NON_ACC_NEG_SESSION_CHAR);
+                       this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 5), PCEPErrors.SECOND_OPEN_MSG);
+                       this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 6), PCEPErrors.PCERR_NON_ACC_SESSION_CHAR);
+                       this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 7), PCEPErrors.NO_MSG_BEFORE_EXP_KEEPWAIT);
+                       this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 8), PCEPErrors.PCEP_VERSION_NOT_SUPPORTED);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 2, (short) 0), PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 3, (short) 1), PCEPErrors.UNRECOGNIZED_OBJ_CLASS);
+                       this.fillIn(new PCEPErrorIdentifier((short) 3, (short) 2), PCEPErrors.UNRECOGNIZED_OBJ_TYPE);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 4, (short) 1), PCEPErrors.NOT_SUPPORTED_OBJ_CLASS);
+                       this.fillIn(new PCEPErrorIdentifier((short) 4, (short) 2), PCEPErrors.NOT_SUPPORTED_OBJ_TYPE);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 1), PCEPErrors.C_BIT_SET);
+                       this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 2), PCEPErrors.O_BIT_SET);
+                       this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 3), PCEPErrors.OF_NOT_ALLOWED);
+                       this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 4), PCEPErrors.OF_BIT_SET);
+                       this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 5), PCEPErrors.GCO_NOT_ALLOWED);
+                       this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 7), PCEPErrors.P2MP_COMPUTATION_NOT_ALLOWED);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 1), PCEPErrors.RP_MISSING);
+                       this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 2), PCEPErrors.RRO_MISSING);
+                       this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 3), PCEPErrors.END_POINTS_MISSING);
+                       this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 8), PCEPErrors.LSP_MISSING);
+                       this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 9), PCEPErrors.ERO_MISSING);
+                       this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 10), PCEPErrors.BANDWIDTH_MISSING);
+                       this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 11), PCEPErrors.LSPA_MISSING);
+                       this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 12), PCEPErrors.DB_VERSION_TLV_MISSING);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 13), PCEPErrors.LSP_CLEANUP_TLV_MISSING);
+                       this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 14), PCEPErrors.SYMBOLIC_PATH_NAME_MISSING);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 7, (short) 0), PCEPErrors.SYNC_PATH_COMP_REQ_MISSING);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 8, (short) 0), PCEPErrors.UNKNOWN_REQ_REF);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 9, (short) 0), PCEPErrors.ATTEMPT_2ND_SESSION);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 10, (short) 1), PCEPErrors.P_FLAG_NOT_SET);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 12, (short) 1), PCEPErrors.UNSUPPORTED_CT);
+                       this.fillIn(new PCEPErrorIdentifier((short) 12, (short) 2), PCEPErrors.INVALID_CT);
+                       this.fillIn(new PCEPErrorIdentifier((short) 12, (short) 3), PCEPErrors.CT_AND_SETUP_PRIORITY_DO_NOT_FORM_TE_CLASS);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 15, (short) 1), PCEPErrors.INSUFFICIENT_MEMORY);
+                       this.fillIn(new PCEPErrorIdentifier((short) 15, (short) 2), PCEPErrors.GCO_NOT_SUPPORTED);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 16, (short) 1), PCEPErrors.CANNOT_SATISFY_P2MP_REQUEST_DUE_TO_INSUFFISIENT_MEMMORY);
+                       this.fillIn(new PCEPErrorIdentifier((short) 16, (short) 2), PCEPErrors.NOT_CAPPABLE_P2MP_COMPUTATION);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 17, (short) 1), PCEPErrors.P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT2);
+                       this.fillIn(new PCEPErrorIdentifier((short) 17, (short) 2), PCEPErrors.P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT3);
+                       this.fillIn(new PCEPErrorIdentifier((short) 17, (short) 3), PCEPErrors.P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT4);
+                       this.fillIn(new PCEPErrorIdentifier((short) 17, (short) 4), PCEPErrors.P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_INCONSISTENT_EP);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 18, (short) 1), PCEPErrors.P2MP_FRAGMENTATION_FAILRUE);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 19, (short) 1), PCEPErrors.UPDATE_REQ_FOR_NON_LSP);
+                       this.fillIn(new PCEPErrorIdentifier((short) 19, (short) 2), PCEPErrors.UPDATE_REQ_FOR_NO_STATEFUL);
+                       //TODO: value TBD
+                       this.fillIn(new PCEPErrorIdentifier((short) 19, (short) 3), PCEPErrors.LSP_LIMIT_REACHED);
+                       this.fillIn(new PCEPErrorIdentifier((short) 19, (short) 4), PCEPErrors.DELEGATION_NOT_REVOKED);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 20, (short) 1), PCEPErrors.CANNOT_PROCESS_STATE_REPORT);
+                       this.fillIn(new PCEPErrorIdentifier((short) 20, (short) 2), PCEPErrors.LSP_DB_VERSION_MISMATCH);
+                       this.fillIn(new PCEPErrorIdentifier((short) 20, (short) 3), PCEPErrors.DB_VERSION_TLV_MISSING_WHEN_SYNC_ALLOWED);
+
+                       this.fillIn(new PCEPErrorIdentifier((short) 23, (short) 1), PCEPErrors.USED_SYMBOLIC_PATH_NAME);
+               }
+
+               private void fillIn(final PCEPErrorIdentifier identifier, final PCEPErrors error) {
+                       this.errorsMap.put(error, identifier);
+                       this.errorIdsMap.put(identifier, error);
+               }
+
+               public PCEPErrorIdentifier getFromErrorsEnum(final PCEPErrors error) {
+                       final PCEPErrorIdentifier ei = this.errorsMap.get(error);
+                       if (ei == null) {
+                               logger.debug("Unknown PCEPErrors type: {}.", error);
+                               throw new NoSuchElementException("Unknown PCEPErrors type: " + error);
+                       }
+                       return ei;
+               }
+
+               public PCEPErrors getFromErrorIdentifier(final PCEPErrorIdentifier identifier) {
+                       final PCEPErrors e = this.errorIdsMap.get(identifier);
+                       if (e == null) {
+                               logger.debug("Unknown error type/value combination: {}.", identifier);
+                               throw new NoSuchElementException("Unknown error type/value combination: " + identifier);
+                       }
+                       return e;
+               }
+
+               public static PCEPErrorsMaping getInstance() {
+                       return instance;
+               }
+       }
+
+       public static final int FLAGS_F_LENGTH = 1;
+       public static final int ET_F_LENGTH = 1;
+       public static final int EV_F_LENGTH = 1;
+
+       public static final int FLAGS_F_OFFSET = 1; //added reserved field of size 1 byte
+       public static final int ET_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+       public static final int EV_F_OFFSET = ET_F_OFFSET + ET_F_LENGTH;
+       public static final int TLVS_OFFSET = EV_F_OFFSET + EV_F_LENGTH;
+
+       private final static Logger logger = LoggerFactory.getLogger(PCEPErrorObjectParser.class);
+
+       @Override
+       public PCEPObject parse(final byte[] bytes, final boolean processed, final boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Array of bytes is mandatory.");
+
+               if (bytes.length < TLVS_OFFSET)
+                       throw new PCEPDeserializerException("Wrong size of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET);
+
+               final PCEPErrorIdentifier eid = new PCEPErrorIdentifier((short) (bytes[ET_F_OFFSET] & 0xFF), (short) (bytes[EV_F_OFFSET] & 0xFF));
+               final PCEPErrors error;
+
+               try {
+                       error = PCEPErrorsMaping.getInstance().getFromErrorIdentifier(eid);
+               } catch (final NoSuchElementException e) {
+                       logger.debug("Failed to identify error {}", eid, e);
+                       throw new PCEPDeserializerException(e, "Error object has unknown identifier.");
+               }
+
+               return new PCEPErrorObject(error, PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_OFFSET)));
+       }
+
+       @Override
+       public byte[] put(final PCEPObject obj) {
+               if (!(obj instanceof PCEPErrorObject))
+                       throw new IllegalArgumentException("Unknown PCEPObject instance.");
+
+               final PCEPErrorObject errObj = (PCEPErrorObject) obj;
+
+               final byte[] tlvs = PCEPTlvParser.put(errObj.getTlvs());
+               final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length];
+
+               ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+               final PCEPErrorIdentifier identifier = PCEPErrorsMaping.getInstance().getFromErrorsEnum(errObj.getError());
+
+               retBytes[ET_F_OFFSET] = ByteArray.shortToBytes(identifier.type)[1];
+               retBytes[EV_F_OFFSET] = ByteArray.shortToBytes(identifier.value)[1];
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPExcludeRouteObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPExcludeRouteObjectParser.java
new file mode 100644 (file)
index 0000000..e511e2f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.List;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPXROSubobjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject
+ * PCEPExcludeRouteObject}
+ */
+public class PCEPExcludeRouteObjectParser implements PCEPObjectParser {
+
+       /*
+        * lengths of fields in bytes
+        */
+       public final int FLAGS_F_LENGTH = 2;
+
+       /*
+        * offsets of fields in bytes
+        */
+       public final int FLAGS_F_OFFSET = 2; // added reserved 2 bytes
+       public final int SO_F_OFFSET = this.FLAGS_F_OFFSET + this.FLAGS_F_LENGTH;
+
+       /*
+        * Flag offsets inside flags field in bits
+        */
+       public final int F_FLAG_OFFSET = 15;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+               final BitSet flags = ByteArray.bytesToBitSet(Arrays.copyOfRange(bytes, this.FLAGS_F_OFFSET, this.FLAGS_F_LENGTH));
+
+               final List<ExcludeRouteSubobject> subobjects = PCEPXROSubobjectParser.parse(ByteArray.cutBytes(bytes, this.SO_F_OFFSET));
+               if (subobjects.isEmpty())
+                       throw new PCEPDeserializerException("Empty Exclude Route Object.");
+
+               return new PCEPExcludeRouteObject(subobjects, flags.get(this.F_FLAG_OFFSET), processed, ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPExcludeRouteObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPExcludeRouteObject.");
+
+               assert !(((PCEPExcludeRouteObject) obj).getSubobjects().isEmpty()) : "Empty Exclude Route Object.";
+
+               final byte[] subObjsBytes = PCEPXROSubobjectParser.put(((PCEPExcludeRouteObject) obj).getSubobjects());
+               final byte[] retBytes = new byte[this.SO_F_OFFSET + subObjsBytes.length];
+               final BitSet flags = new BitSet(this.FLAGS_F_LENGTH * Byte.SIZE);
+               flags.set(this.F_FLAG_OFFSET, ((PCEPExcludeRouteObject) obj).isFail());
+               ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, this.FLAGS_F_LENGTH), retBytes, this.FLAGS_F_OFFSET);
+               ByteArray.copyWhole(subObjsBytes, retBytes, this.SO_F_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPExistingPathBandwidthObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPExistingPathBandwidthObjectParser.java
new file mode 100644 (file)
index 0000000..f7f03c9
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject
+ * PCEPExistingPathBandwidthObject}
+ */
+public class PCEPExistingPathBandwidthObjectParser implements PCEPObjectParser {
+
+       private static final int BANDWIDTH_F_LENGTH = 4;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Array of bytes is mandatory");
+               if (bytes.length != BANDWIDTH_F_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: " + BANDWIDTH_F_LENGTH + ".");
+
+               return new PCEPExistingPathBandwidthObject(new Bandwidth(ByteArray.bytesToFloat(bytes)), processed, ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPExistingPathBandwidthObject))
+                       throw new IllegalArgumentException("Unknown PCEPObject instance.");
+
+               return ByteArray.floatToBytes((float) ((PCEPExistingPathBandwidthObject) obj).getBandwidth().getBytesPerSecond());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPExplicitRouteObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPExplicitRouteObjectParser.java
new file mode 100644 (file)
index 0000000..aad0c00
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPEROSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject
+ * PCEPExplicitRouteObject}
+ */
+public class PCEPExplicitRouteObjectParser implements PCEPObjectParser {
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+               final List<ExplicitRouteSubobject> subobjects = PCEPEROSubobjectParser.parse(bytes);
+               if (subobjects.isEmpty())
+                       throw new PCEPDeserializerException("Empty Explicit Route Object.");
+
+               return new PCEPExplicitRouteObject(subobjects, ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPExplicitRouteObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPExplicitRouteObject.");
+
+               assert !(((PCEPExplicitRouteObject) obj).getSubobjects().isEmpty()) : "Empty Explicit Route Object.";
+
+               return PCEPEROSubobjectParser.put(((PCEPExplicitRouteObject) obj).getSubobjects());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPGlobalConstraintsObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPGlobalConstraintsObjectParser.java
new file mode 100644 (file)
index 0000000..13795b4
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject
+ * PCEPGlobalConstraints}
+ */
+public class PCEPGlobalConstraintsObjectParser implements PCEPObjectParser {
+
+       private final static int MAX_HOP_F_LENGTH = 1;
+       private final static int MAX_UTIL_F_LENGTH = 1;
+       private final static int MIN_UTIL_F_LENGTH = 1;
+       private final static int OVER_BOOKING_FACTOR_F_LENGTH = 1;
+
+       private final static int MAX_HOP_F_OFFSET = 0;
+       private final static int MAX_UTIL_F_OFFSET = MAX_HOP_F_OFFSET + MAX_HOP_F_LENGTH;
+       private final static int MIN_UTIL_F_OFFSET = MAX_UTIL_F_OFFSET + MAX_UTIL_F_LENGTH;
+       private final static int OVER_BOOKING_FACTOR_F_OFFSET = MIN_UTIL_F_OFFSET + MIN_UTIL_F_LENGTH;
+
+       private final static int TLVS_OFFSET = OVER_BOOKING_FACTOR_F_OFFSET + OVER_BOOKING_FACTOR_F_LENGTH;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+               if (bytes.length < TLVS_OFFSET)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+               return new PCEPGlobalConstraintsObject((short) (bytes[MAX_HOP_F_OFFSET] & 0xFF), (short) (bytes[MAX_UTIL_F_OFFSET] & 0xFF),
+                               (short) (bytes[MIN_UTIL_F_OFFSET] & 0xFF), (short) (bytes[OVER_BOOKING_FACTOR_F_OFFSET] & 0xFF), PCEPTlvParser.parse(ByteArray.cutBytes(bytes,
+                                               TLVS_OFFSET)), processed, ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPGlobalConstraintsObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPGlobalConstraints.");
+
+               final PCEPGlobalConstraintsObject specObj = (PCEPGlobalConstraintsObject) obj;
+
+               final byte[] tlvs = PCEPTlvParser.put(specObj.getTlvs());
+               final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length];
+
+               retBytes[MAX_HOP_F_OFFSET] = (byte) specObj.getMaxHop();
+               retBytes[MAX_UTIL_F_OFFSET] = (byte) specObj.getMaxUtilization();
+               retBytes[MIN_UTIL_F_OFFSET] = (byte) specObj.getMinUtilization();
+               retBytes[OVER_BOOKING_FACTOR_F_OFFSET] = (byte) specObj.getOverBookingFactor();
+
+               ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPIncludeRouteObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPIncludeRouteObjectParser.java
new file mode 100644 (file)
index 0000000..60e1cc3
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPEROSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject
+ * PCEPIncludeRouteObject}
+ */
+public class PCEPIncludeRouteObjectParser implements PCEPObjectParser {
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+               final List<ExplicitRouteSubobject> subobjects = PCEPEROSubobjectParser.parse(bytes);
+               if (subobjects.isEmpty())
+                       throw new PCEPDeserializerException("Empty Include Route Object.");
+
+               return new PCEPIncludeRouteObject(subobjects, processed, ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPIncludeRouteObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPIncludeRouteObject.");
+
+               assert !(((PCEPIncludeRouteObject) obj).getSubobjects().isEmpty()) : "Empty Include Route Object.";
+
+               return PCEPEROSubobjectParser.put(((PCEPIncludeRouteObject) obj).getSubobjects());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPLoadBalancingObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPLoadBalancingObjectParser.java
new file mode 100644 (file)
index 0000000..84a02ae
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject
+ * PCEPLoadBalancingObject}
+ */
+public class PCEPLoadBalancingObjectParser implements PCEPObjectParser {
+
+       public static final int FLAGS_F_LENGTH = 1;
+       public static final int MAX_LSP_F_LENGTH = 1;
+       public static final int MIN_BAND_F_LENGTH = 4;
+
+       public static final int FLAGS_F_OFFSET = 2;
+       public static final int MAX_LSP_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+       public static final int MIN_BAND_F_OFFSET = MAX_LSP_F_OFFSET + MAX_LSP_F_LENGTH;
+
+       public static final int SIZE = MIN_BAND_F_OFFSET + MIN_BAND_F_LENGTH;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+               if (bytes.length != SIZE)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: " + SIZE + ".");
+
+               return new PCEPLoadBalancingObject(bytes[MAX_LSP_F_OFFSET] & 0xFF, new Bandwidth(ByteArray.bytesToFloat(ByteArray.subByte(bytes, MIN_BAND_F_OFFSET,
+                               MIN_BAND_F_LENGTH))), processed);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPLoadBalancingObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPLoadBalancingObject.");
+
+               final PCEPLoadBalancingObject specObj = (PCEPLoadBalancingObject) obj;
+
+               final byte[] retBytes = new byte[SIZE];
+
+               retBytes[MAX_LSP_F_OFFSET] = ByteArray.intToBytes(specObj.getMaxLSP())[Integer.SIZE / Byte.SIZE - 1];
+               ByteArray.copyWhole(ByteArray.floatToBytes((float) specObj.getMinBandwidth().getBytesPerSecond()), retBytes, MIN_BAND_F_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPLspObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPLspObjectParser.java
new file mode 100644 (file)
index 0000000..517e01e
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPLspObject PCEPLspObject}
+ */
+public class PCEPLspObjectParser implements PCEPObjectParser {
+
+       /*
+        * offset of TLVs offset of other fields are not defined as constants
+        * because of non-standard mapping of bits
+        */
+       public static final int TLVS_OFFSET = 4;
+
+       /*
+        * 12b extended to 16b so first 4b are restricted (belongs to LSP ID)
+        */
+       private static final int DELEGATE_FLAG_OFFSET = 15;
+       private static final int OPERATIONAL_FLAG_OFFSET = 13;
+       private static final int SYNC_FLAG_OFFSET = 14;
+       private static final int REMOVE_FLAG_OFFSET = 12;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+               if (bytes.length < TLVS_OFFSET)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+               final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(bytes, 2, 2));
+
+               return new PCEPLspObject((ByteArray.bytesToShort(ByteArray.subByte(bytes, 0, 2)) & 0xFFFF) << 4 | (bytes[2] & 0xFF) >> 4,
+                               flags.get(DELEGATE_FLAG_OFFSET), flags.get(SYNC_FLAG_OFFSET), flags.get(OPERATIONAL_FLAG_OFFSET), flags.get(REMOVE_FLAG_OFFSET),
+                               PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_OFFSET)));
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPLspObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPLspObject.");
+
+               final PCEPLspObject specObj = (PCEPLspObject) obj;
+
+               final byte[] tlvs = PCEPTlvParser.put(specObj.getTlvs());
+
+               final byte[] retBytes = new byte[tlvs.length + TLVS_OFFSET];
+
+               final int lspID = specObj.getLspID();
+               retBytes[0] = (byte) (lspID >> 12);
+               retBytes[1] = (byte) (lspID >> 4);
+               retBytes[2] = (byte) (lspID << 4);
+               if (specObj.isDelegate())
+                       retBytes[3] |= 1 << (Byte.SIZE - (DELEGATE_FLAG_OFFSET - Byte.SIZE) - 1);
+               if (specObj.isOperational())
+                       retBytes[3] |= 1 << (Byte.SIZE - (OPERATIONAL_FLAG_OFFSET - Byte.SIZE) - 1);
+               if (specObj.isRemove())
+                       retBytes[3] |= 1 << (Byte.SIZE - (REMOVE_FLAG_OFFSET - Byte.SIZE) - 1);
+               if (specObj.isSync())
+                       retBytes[3] |= 1 << (Byte.SIZE - (SYNC_FLAG_OFFSET - Byte.SIZE) - 1);
+
+               ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPLspaObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPLspaObjectParser.java
new file mode 100644 (file)
index 0000000..6cbe71d
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPLspaObject PCEPLspaObject}
+ */
+public class PCEPLspaObjectParser implements PCEPObjectParser {
+
+       /*
+        * lenghts of fields in bytes
+        */
+       public static final int EXC_ANY_F_LENGTH = 4;
+       public static final int INC_ANY_F_LENGTH = 4;
+       public static final int INC_ALL_F_LENGTH = 4;
+       public static final int SET_PRIO_F_LENGTH = 1;
+       public static final int HOLD_PRIO_F_LENGTH = 1;
+       public static final int FLAGS_F_LENGTH = 1;
+
+       /*
+        * offsets of flags inside flags field in bits
+        */
+       public static final int S_FLAG_OFFSET = 6;
+       public static final int L_FLAG_OFFSET = 7;
+
+       /*
+        * offsets of fields in bytes
+        */
+       public static final int EXC_ANY_F_OFFSET = 0;
+       public static final int INC_ANY_F_OFFSET = EXC_ANY_F_OFFSET + EXC_ANY_F_LENGTH;
+       public static final int INC_ALL_F_OFFSET = INC_ANY_F_OFFSET + INC_ANY_F_LENGTH;
+       public static final int SET_PRIO_F_OFFSET = INC_ALL_F_OFFSET + INC_ALL_F_LENGTH;
+       public static final int HOLD_PRIO_F_OFFSET = SET_PRIO_F_OFFSET + SET_PRIO_F_LENGTH;
+       public static final int FLAGS_F_OFFSET = HOLD_PRIO_F_OFFSET + HOLD_PRIO_F_LENGTH;
+       public static final int TLVS_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH + 1; //added reserved field of length 1B
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null)
+                       throw new IllegalArgumentException("Bytes array is mandatory.");
+
+               final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(bytes, FLAGS_F_OFFSET, FLAGS_F_LENGTH));
+
+               return new PCEPLspaObject(UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(bytes, EXC_ANY_F_OFFSET, EXC_ANY_F_LENGTH))),
+                               UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(bytes, INC_ANY_F_OFFSET, INC_ANY_F_LENGTH))), UnsignedInts.toLong(ByteArray
+                                               .bytesToInt(ByteArray.subByte(bytes, INC_ALL_F_OFFSET, INC_ALL_F_LENGTH))), (short) (bytes[SET_PRIO_F_OFFSET] & 0xFF),
+                               (short) (bytes[HOLD_PRIO_F_OFFSET] & 0xFF), flags.get(S_FLAG_OFFSET), flags.get(L_FLAG_OFFSET), PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_F_OFFSET)), processed,
+                               ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPLspaObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPLspaObject.");
+
+               final PCEPLspaObject lspaObj = (PCEPLspaObject) obj;
+
+               final byte[] tlvs = PCEPTlvParser.put(lspaObj.getTlvs());
+               final byte[] retBytes = new byte[TLVS_F_OFFSET + tlvs.length];
+               ByteArray.copyWhole(tlvs, retBytes, TLVS_F_OFFSET);
+
+               System.arraycopy(ByteArray.longToBytes(lspaObj.getExcludeAny()), 4, retBytes, EXC_ANY_F_OFFSET, EXC_ANY_F_LENGTH);
+               System.arraycopy(ByteArray.longToBytes(lspaObj.getIncludeAny()), 4, retBytes, INC_ANY_F_OFFSET, INC_ANY_F_LENGTH);
+               System.arraycopy(ByteArray.longToBytes(lspaObj.getIncludeAll()), 4, retBytes, INC_ALL_F_OFFSET, INC_ALL_F_LENGTH);
+               retBytes[SET_PRIO_F_OFFSET] = ByteArray.shortToBytes(lspaObj.getSetupPriority())[Short.SIZE / Byte.SIZE - 1];
+               retBytes[HOLD_PRIO_F_OFFSET] = ByteArray.shortToBytes(lspaObj.getHoldingPriority())[Short.SIZE / Byte.SIZE - 1];
+
+               final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+               flags.set(S_FLAG_OFFSET, lspaObj.isStandByPath());
+               flags.set(L_FLAG_OFFSET, lspaObj.isLocalProtected());
+               ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPMetricObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPMetricObjectParser.java
new file mode 100644 (file)
index 0000000..2696e29
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.concepts.AggregateBandwidthConsumptionMetric;
+import org.opendaylight.protocol.pcep.concepts.CumulativeIGPCostMetric;
+import org.opendaylight.protocol.pcep.concepts.CumulativeTECostMetric;
+import org.opendaylight.protocol.pcep.concepts.MostLoadedLinkLoadMetric;
+import org.opendaylight.protocol.pcep.concepts.P2MPHopCountMetric;
+import org.opendaylight.protocol.pcep.concepts.P2MPIGPMetric;
+import org.opendaylight.protocol.pcep.concepts.P2MPTEMetric;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPMetricObject
+ * PCEPMetricObject}
+ */
+public class PCEPMetricObjectParser implements PCEPObjectParser {
+
+       /*
+        * lengths of fields in bytes
+        */
+       private static final int FLAGS_F_LENGTH = 1;
+       private static final int TYPE_F_LENGTH = 1;
+       private static final int METRIC_VALUE_F_LENGTH = 4;
+
+       /*
+        * offsets of fields in bytes
+        */
+       public static final int FLAGS_F_OFFSET = 2;
+       public static final int TYPE_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+       public static final int METRIC_VALUE_F_OFFSET = TYPE_F_OFFSET + TYPE_F_LENGTH;
+
+       /*
+        * flags offsets inside flags field in bits
+        */
+       private static final int C_FLAG_OFFSET = 6;
+       private static final int B_FLAG_OFFSET = 7;
+
+       public static final int SIZE = METRIC_VALUE_F_OFFSET + METRIC_VALUE_F_LENGTH;
+
+       /**
+        * Bidirectional mapping for metrics. Maps metric class to integer and
+        * integer to metrics instantiable.
+        */
+       public static class PCEPMetricsMapping {
+               private static final PCEPMetricsMapping instance = new PCEPMetricsMapping();
+
+               private final Map<Class<?>, Integer> metricsMap = new HashMap<Class<?>, Integer>();
+               private final Map<Integer, InstantiableMetric> metrictTypesMap = new HashMap<Integer, InstantiableMetric>();
+
+               private interface InstantiableMetric {
+                       public AbstractMetric<?> getMetric(long metric);
+               }
+
+               private PCEPMetricsMapping() {
+                       this.fillIn();
+               }
+
+               private void fillIn() {
+                       this.fillIn(1, IGPMetric.class, new InstantiableMetric() {
+
+                               @Override
+                               public AbstractMetric<?> getMetric(long metric) {
+                                       return new IGPMetric(metric);
+                               }
+
+                       });
+                       this.fillIn(2, TEMetric.class, new InstantiableMetric() {
+
+                               @Override
+                               public AbstractMetric<?> getMetric(long metric) {
+                                       return new TEMetric(metric);
+                               }
+
+                       });
+                       this.fillIn(4, AggregateBandwidthConsumptionMetric.class, new InstantiableMetric() {
+
+                               @Override
+                               public AbstractMetric<?> getMetric(long metric) {
+                                       return new AggregateBandwidthConsumptionMetric(metric);
+                               }
+
+                       });
+                       this.fillIn(5, MostLoadedLinkLoadMetric.class, new InstantiableMetric() {
+
+                               @Override
+                               public AbstractMetric<?> getMetric(long metric) {
+                                       return new MostLoadedLinkLoadMetric(metric);
+                               }
+
+                       });
+                       this.fillIn(6, CumulativeIGPCostMetric.class, new InstantiableMetric() {
+
+                               @Override
+                               public AbstractMetric<?> getMetric(long metric) {
+                                       return new CumulativeIGPCostMetric(metric);
+                               }
+
+                       });
+                       this.fillIn(7, CumulativeTECostMetric.class, new InstantiableMetric() {
+
+                               @Override
+                               public AbstractMetric<?> getMetric(long metric) {
+                                       return new CumulativeTECostMetric(metric);
+                               }
+
+                       });
+                       this.fillIn(8, P2MPIGPMetric.class, new InstantiableMetric() {
+
+                               @Override
+                               public AbstractMetric<?> getMetric(long metric) {
+                                       return new P2MPIGPMetric(metric);
+                               }
+
+                       });
+                       this.fillIn(9, P2MPTEMetric.class, new InstantiableMetric() {
+
+                               @Override
+                               public AbstractMetric<?> getMetric(long metric) {
+                                       return new P2MPHopCountMetric(metric);
+                               }
+
+                       });
+                       this.fillIn(10, P2MPHopCountMetric.class, new InstantiableMetric() {
+
+                               @Override
+                               public AbstractMetric<?> getMetric(long metric) {
+                                       return new P2MPHopCountMetric(metric);
+                               }
+
+                       });
+               }
+
+               private void fillIn(int type, Class<?> metricClazz, InstantiableMetric instantiable) {
+                       this.metricsMap.put(metricClazz, type);
+                       this.metrictTypesMap.put(type, instantiable);
+               }
+
+               public int getFromMetricClass(Class<? extends AbstractMetric<?>> clazz) {
+                       final Integer mi = this.metricsMap.get(clazz);
+                       if (mi == null)
+                               throw new NoSuchElementException("Unknown Metric: " + clazz);
+                       return mi;
+               }
+
+               public AbstractMetric<?> getFromMetricTypeIdentifier(int identifier, long metric) {
+                       final InstantiableMetric e = this.metrictTypesMap.get(identifier);
+                       if (e == null)
+                               throw new NoSuchElementException("Unknown metric type identifier. Passed: " + identifier);
+                       return e.getMetric(metric);
+               }
+
+               public static PCEPMetricsMapping getInstance() {
+                       return instance;
+               }
+       }
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+               if (bytes.length != SIZE)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: " + SIZE + ".");
+
+               final byte[] flagBytes = { bytes[FLAGS_F_OFFSET] };
+               final BitSet flags = ByteArray.bytesToBitSet(flagBytes);
+               try {
+                       return new PCEPMetricObject(flags.get(B_FLAG_OFFSET), flags.get(C_FLAG_OFFSET), PCEPMetricsMapping.getInstance().getFromMetricTypeIdentifier(
+                                       (short) (bytes[TYPE_F_OFFSET] & 0xFF),
+                                       (long) ByteArray.bytesToFloat(ByteArray.subByte(bytes, METRIC_VALUE_F_OFFSET, METRIC_VALUE_F_LENGTH))), processed, ignored);
+               } catch (final NoSuchElementException e) {
+                       throw new PCEPDeserializerException(e, "Metric object has unknown identifier.");
+               }
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPMetricObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPMetricObject.");
+
+               final PCEPMetricObject mObj = (PCEPMetricObject) obj;
+
+               final byte[] retBytes = new byte[SIZE];
+               final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+               flags.set(C_FLAG_OFFSET, mObj.isComputedMetric());
+               flags.set(B_FLAG_OFFSET, mObj.isBound());
+
+               ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+               final AbstractMetric<?> metric = mObj.getMetric();
+               @SuppressWarnings("unchecked")
+               final Class<? extends AbstractMetric<?>> metricClazz = (Class<? extends AbstractMetric<?>>) metric.getClass();
+               retBytes[TYPE_F_OFFSET] = (byte) PCEPMetricsMapping.getInstance().getFromMetricClass(metricClazz);
+
+               System.arraycopy(ByteArray.floatToBytes(mObj.getMetric().getValue()), 0, retBytes, METRIC_VALUE_F_OFFSET, METRIC_VALUE_F_LENGTH);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPNoPathObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPNoPathObjectParser.java
new file mode 100644 (file)
index 0000000..9546831
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPNoPathObject
+ * PCEPNoPathObject}
+ */
+public class PCEPNoPathObjectParser implements PCEPObjectParser {
+
+       /*
+        * lengths of fields in bytes
+        */
+       public static final int NI_F_LENGTH = 1; //multi-field
+       public static final int FLAGS_F_LENGTH = 2;
+       public static final int RESERVED_F_LENGTH = 1;
+
+       /*
+        * offsets of field in bytes
+        */
+
+       public static final int NI_F_OFFSET = 0;
+       public static final int FLAGS_F_OFFSET = NI_F_OFFSET + NI_F_LENGTH;
+       public static final int RESERVED_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+       public static final int TLVS_OFFSET = RESERVED_F_OFFSET + RESERVED_F_LENGTH;
+
+       /*
+        * defined flags
+        */
+
+       public static final int C_FLAG_OFFSET = 0;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+               final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(bytes, FLAGS_F_OFFSET, FLAGS_F_LENGTH));
+
+               if (bytes.length < TLVS_OFFSET)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+               return new PCEPNoPathObject((short) (bytes[NI_F_OFFSET] & 0xFF), flags.get(C_FLAG_OFFSET), PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_OFFSET)),
+                               ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPNoPathObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPNoPathObject.");
+
+               final PCEPNoPathObject nPObj = (PCEPNoPathObject) obj;
+
+               final byte[] tlvs = PCEPTlvParser.put(nPObj.getTlvs());
+               final byte[] retBytes = new byte[tlvs.length + TLVS_OFFSET];
+               final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+               flags.set(C_FLAG_OFFSET, nPObj.isConstrained());
+               retBytes[NI_F_OFFSET] = ByteArray.shortToBytes(nPObj.getNatureOfIssue())[1];
+               ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+               ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPNonBranchNodeListObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPNonBranchNodeListObjectParser.java
new file mode 100644 (file)
index 0000000..dd1fb9b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPEROSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPNonBranchNodeListObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+public class PCEPNonBranchNodeListObjectParser implements PCEPObjectParser {
+
+       @Override
+       public PCEPNonBranchNodeListObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+               final List<ExplicitRouteSubobject> subobjects = PCEPEROSubobjectParser.parse(bytes);
+               if (subobjects.isEmpty())
+                       throw new PCEPDeserializerException("Empty Non-Branch Node List Object.");
+
+               return new PCEPNonBranchNodeListObject(subobjects, processed, ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPNonBranchNodeListObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPNonBranchNodeListObject.");
+
+               assert !(((PCEPNonBranchNodeListObject) obj).getSubobjects().isEmpty()) : "Empty Non-Branch Node List Object.";
+
+               return PCEPEROSubobjectParser.put(((PCEPNonBranchNodeListObject) obj).getSubobjects());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPNotificationObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPNotificationObjectParser.java
new file mode 100644 (file)
index 0000000..7f277b7
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPNotificationObject
+ * PCEPNotificationObject}
+ */
+public class PCEPNotificationObjectParser implements PCEPObjectParser {
+
+       /*
+        * lengths of fields
+        */
+       public static final int FLAGS_F_LENGTH = 1;
+       public static final int NT_F_LENGTH = 1;
+       public static final int NV_F_LENGTH = 1;
+
+       /*
+        * offsets of fields
+        */
+       public static final int FLAGS_F_OFFSET = 1; //added reserved filed of size 1
+       public static final int NT_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+       public static final int NV_F_OFFSET = NT_F_OFFSET + NT_F_LENGTH;
+       public static final int TLVS_OFFSET = NV_F_OFFSET + NV_F_LENGTH;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+               if (bytes.length < TLVS_OFFSET)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+               return new PCEPNotificationObject((short) (bytes[NT_F_OFFSET] & 0xFF), (short) (bytes[NV_F_OFFSET] & 0xFF), PCEPTlvParser.parse(ByteArray.cutBytes(
+                               bytes, TLVS_OFFSET)));
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPNotificationObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPNotificationObject.");
+
+               final PCEPNotificationObject notObj = (PCEPNotificationObject) obj;
+
+               final byte[] tlvs = PCEPTlvParser.put(notObj.getTlvs());
+               final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length];
+
+               ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+               retBytes[NT_F_OFFSET] = ByteArray.shortToBytes(notObj.getType())[1];
+               retBytes[NV_F_OFFSET] = ByteArray.shortToBytes(notObj.getValue())[1];
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPObjectiveFunctionObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPObjectiveFunctionObjectParser.java
new file mode 100644 (file)
index 0000000..d82f060
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.NoSuchElementException;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPOFCodesMapping;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject
+ * PCEPObjectiveFunctionObject}
+ */
+public class PCEPObjectiveFunctionObjectParser implements PCEPObjectParser {
+
+       /*
+        * lengths of fields
+        */
+       public static final int OF_CODE_F_LENGTH = 2;
+
+       /*
+        * offsets of fields
+        */
+       public static final int OF_CODE_F_OFFSET = 0;
+       public static final int TLVS_OFFSET = OF_CODE_F_OFFSET + OF_CODE_F_LENGTH + 2; // added reserved field of size 2
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+               if (bytes.length < TLVS_OFFSET)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+               try {
+                       return new PCEPObjectiveFunctionObject(PCEPOFCodesMapping.getInstance().getFromCodeIdentifier(
+                                       ByteArray.bytesToShort(ByteArray.subByte(bytes, OF_CODE_F_OFFSET, OF_CODE_F_LENGTH)) & 0xFFFF), PCEPTlvParser.parse(ByteArray.cutBytes(
+                                       bytes, TLVS_OFFSET)), processed, ignored);
+               } catch (final NoSuchElementException e) {
+                       throw new PCEPDeserializerException(e, "Objective function object has unknown identifier.");
+               }
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPObjectiveFunctionObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPObjectiveFunction.");
+
+               final PCEPObjectiveFunctionObject specObj = (PCEPObjectiveFunctionObject) obj;
+
+               final byte[] tlvs = PCEPTlvParser.put(specObj.getTlvs());
+               final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length];
+
+               ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+               ByteArray.copyWhole(ByteArray.shortToBytes((short) PCEPOFCodesMapping.getInstance().getFromOFCodesEnum(specObj.getCode())), retBytes, OF_CODE_F_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPOpenObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPOpenObjectParser.java
new file mode 100644 (file)
index 0000000..e9f7b39
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.impl.Util;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.tlv.OFListTlv;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPOpenObject PCEPOpenObject}
+ */
+
+public class PCEPOpenObjectParser implements PCEPObjectParser {
+
+       /*
+        * lengths of fields in bytes
+        */
+       public static final int VER_FLAGS_MF_LENGTH = 1; // multi-field
+       public static final int KEEPALIVE_F_LENGTH = 1;
+       public static final int DEAD_TIMER_LENGTH = 1;
+       public static final int SID_F_LENGTH = 1;
+
+       /*
+        * lengths of subfields inside multi-field in bits
+        */
+       public static final int VERSION_SF_LENGTH = 3;
+       public static final int FLAGS_SF_LENGTH = 5;
+
+       /*
+        * offsets of field in bytes
+        */
+
+       public static final int VER_FLAGS_MF_OFFSET = 0;
+       public static final int KEEPALIVE_F_OFFSET = VER_FLAGS_MF_OFFSET + VER_FLAGS_MF_LENGTH;
+       public static final int DEAD_TIMER_OFFSET = KEEPALIVE_F_OFFSET + KEEPALIVE_F_LENGTH;
+       public static final int SID_F_OFFSET = DEAD_TIMER_OFFSET + DEAD_TIMER_LENGTH;
+       public static final int TLVS_OFFSET = SID_F_OFFSET + SID_F_LENGTH;
+
+       /*
+        * offsets of subfields inside multi-field in bits
+        */
+
+       public static final int VERSION_SF_OFFSET = 0;
+       public static final int FLAGS_SF_OFFSET = VERSION_SF_LENGTH + VERSION_SF_OFFSET;
+
+       public static final int PADDED_TO = 4;
+
+       @Override
+       public PCEPOpenObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+               if (bytes.length < TLVS_OFFSET)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+               // parse version
+               final int versionValue = ByteArray.copyBitsRange(bytes[VER_FLAGS_MF_OFFSET], VERSION_SF_OFFSET, VERSION_SF_LENGTH);
+
+               if (versionValue != PCEPOpenObject.PCEP_VERSION)
+                       throw new PCEPDocumentedException("Unsupported PCEP version " + versionValue, PCEPErrors.PCEP_VERSION_NOT_SUPPORTED);
+
+               final List<PCEPTlv> tlvs = PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_OFFSET));
+               boolean ofListOccure = false;
+
+               for (final PCEPTlv tlv : tlvs) {
+                       if (tlv instanceof OFListTlv) {
+                               if (ofListOccure)
+                                       throw new PCEPDocumentedException("Invalid or unexpected message", PCEPErrors.NON_OR_INVALID_OPEN_MSG);
+
+                               ofListOccure = true;
+                       }
+               }
+
+               return new PCEPOpenObject(UnsignedBytes.toInt(bytes[KEEPALIVE_F_OFFSET]), UnsignedBytes.toInt(bytes[DEAD_TIMER_OFFSET]),
+                               UnsignedBytes.toInt(bytes[SID_F_OFFSET]), tlvs);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPOpenObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPOpenObject.");
+
+               final PCEPOpenObject openObj = (PCEPOpenObject) obj;
+
+               final byte versionFlagMF = (byte) (PCEPOpenObject.PCEP_VERSION << (Byte.SIZE - VERSION_SF_LENGTH));
+
+               final byte[] tlvs = PCEPTlvParser.put(openObj.getTlvs());
+               final byte[] bytes = new byte[TLVS_OFFSET + tlvs.length + Util.getPadding(TLVS_OFFSET + tlvs.length, PADDED_TO)];
+
+               // serialize version_flags multi-field
+               bytes[VER_FLAGS_MF_OFFSET] = versionFlagMF;
+
+               // serialize keepalive
+               bytes[KEEPALIVE_F_OFFSET] = (byte) openObj.getKeepAliveTimerValue();
+
+               // serialize dead timer
+               bytes[DEAD_TIMER_OFFSET] = (byte) openObj.getDeadTimerValue();
+
+               // serialize SID
+               bytes[SID_F_OFFSET] = (byte) openObj.getSessionId();
+
+               // serialize tlvs
+               ByteArray.copyWhole(tlvs, bytes, TLVS_OFFSET);
+
+               return bytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPP2MPEndPointsIPv4ObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPP2MPEndPointsIPv4ObjectParser.java
new file mode 100644 (file)
index 0000000..5b1196a
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.Util;
+import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for IPv4 {@link org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject
+ * PCEPP2MPEndPointsObject}
+ */
+public class PCEPP2MPEndPointsIPv4ObjectParser implements PCEPObjectParser {
+
+    /*
+     * fields lengths and offsets for IPv4 in bytes
+     */
+    public static final int LEAF_TYPE_F_LENGTH = 4;
+    public static final int SRC4_F_LENGTH = 4;
+    public static final int DEST4_F_LENGTH = 4;
+
+    public static final int LEAF_TYPE_F_OFFSET = 0;
+    public static final int SRC4_F_OFFSET = LEAF_TYPE_F_OFFSET + LEAF_TYPE_F_LENGTH;
+    public static final int DEST4_F_OFFSET = SRC4_F_OFFSET + SRC4_F_LENGTH;
+
+    @Override
+    public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+       if (bytes == null)
+           throw new IllegalArgumentException("Array of bytes is mandatory");
+       if (bytes.length < LEAF_TYPE_F_LENGTH + SRC4_F_LENGTH + DEST4_F_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes.");
+
+       final long leafType = UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(bytes, LEAF_TYPE_F_OFFSET, LEAF_TYPE_F_LENGTH)));
+
+       return new PCEPP2MPEndPointsObject<IPv4Address>(leafType, new IPv4Address(
+               ByteArray.subByte(bytes, SRC4_F_OFFSET, SRC4_F_LENGTH)), Util.parseAddresses(bytes, DEST4_F_OFFSET, IPv4.FAMILY,
+               DEST4_F_LENGTH), processed, ignored);
+    }
+
+    @Override
+    public byte[] put(PCEPObject obj) {
+       if (!(obj instanceof PCEPP2MPEndPointsObject))
+           throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPP2MPEndPointsObject.");
+
+       final PCEPP2MPEndPointsObject<?> ePObj = (PCEPP2MPEndPointsObject<?>) obj;
+
+       if (!(ePObj.getSourceAddress() instanceof IPv4Address))
+           throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + ePObj.getSourceAddress().getClass() + ". Needed IPv4Address");
+
+       final byte[] retBytes = new byte[LEAF_TYPE_F_LENGTH + SRC4_F_LENGTH + DEST4_F_LENGTH * ePObj.getDestinationAddresses().size()];
+       ByteArray.copyWhole(ByteArray.intToBytes((int) ePObj.getLeafType()), retBytes, LEAF_TYPE_F_OFFSET);
+       ByteArray.copyWhole(((IPv4Address) ePObj.getSourceAddress()).getAddress(), retBytes, SRC4_F_OFFSET);
+       Util.putAddresses(retBytes, DEST4_F_OFFSET, ePObj.getDestinationAddresses(), DEST4_F_LENGTH);
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPP2MPEndPointsIPv6ObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPP2MPEndPointsIPv6ObjectParser.java
new file mode 100644 (file)
index 0000000..38f218c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.Util;
+import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for IPv4 {@link org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject
+ * PCEPP2MPEndPointsObject}
+ */
+public class PCEPP2MPEndPointsIPv6ObjectParser implements PCEPObjectParser {
+
+    /*
+     * fields lengths and offsets for IPv4 in bytes
+     */
+    public static final int LEAF_TYPE_F_LENGTH = 4;
+    public static final int SRC6_F_LENGTH = 16;
+    public static final int DEST6_F_LENGTH = 16;
+
+    public static final int LEAF_TYPE_F_OFFSET = 0;
+    public static final int SRC6_F_OFFSET = LEAF_TYPE_F_OFFSET + LEAF_TYPE_F_LENGTH;
+    public static final int DEST6_F_OFFSET = SRC6_F_OFFSET + SRC6_F_LENGTH;
+
+    @Override
+    public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+       if (bytes == null)
+           throw new IllegalArgumentException("Array of bytes is mandatory");
+       if (bytes.length < LEAF_TYPE_F_LENGTH + SRC6_F_LENGTH + DEST6_F_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes.");
+
+       final long leafType = UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(bytes, LEAF_TYPE_F_OFFSET, LEAF_TYPE_F_LENGTH)));
+
+       return new PCEPP2MPEndPointsObject<IPv6Address>(leafType, new IPv6Address(
+               ByteArray.subByte(bytes, SRC6_F_OFFSET, SRC6_F_LENGTH)), Util.parseAddresses(bytes, DEST6_F_OFFSET, IPv6.FAMILY,
+               DEST6_F_LENGTH), processed, ignored);
+    }
+
+    @Override
+    public byte[] put(PCEPObject obj) {
+       if (!(obj instanceof PCEPP2MPEndPointsObject))
+           throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPP2MPEndPointsObject.");
+
+       final PCEPP2MPEndPointsObject<?> ePObj = (PCEPP2MPEndPointsObject<?>) obj;
+
+       if (!(ePObj.getSourceAddress() instanceof IPv6Address))
+           throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + ePObj.getSourceAddress().getClass() + ". Needed IPv6Address");
+
+       final byte[] retBytes = new byte[LEAF_TYPE_F_LENGTH + SRC6_F_LENGTH + DEST6_F_LENGTH * ePObj.getDestinationAddresses().size()];
+       ByteArray.copyWhole(ByteArray.intToBytes((int) ePObj.getLeafType()), retBytes, LEAF_TYPE_F_OFFSET);
+       ByteArray.copyWhole(((IPv6Address) ePObj.getSourceAddress()).getAddress(), retBytes, SRC6_F_OFFSET);
+       Util.putAddresses(retBytes, DEST6_F_OFFSET, ePObj.getDestinationAddresses(), DEST6_F_LENGTH);
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPReportedRouteObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPReportedRouteObjectParser.java
new file mode 100644 (file)
index 0000000..f6fc8c3
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPRROSubobjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject
+ * PCEPReportedRouteObject}
+ */
+public class PCEPReportedRouteObjectParser implements PCEPObjectParser {
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+               final List<ReportedRouteSubobject> subobjects = PCEPRROSubobjectParser.parse(bytes);
+               if (subobjects.isEmpty())
+                       throw new PCEPDeserializerException("Empty Reported Route Object.");
+
+               return new PCEPReportedRouteObject(subobjects, processed);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+
+               if (!(obj instanceof PCEPReportedRouteObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPReportedRouteObject.");
+
+               assert !(((PCEPReportedRouteObject) obj).getSubobjects().isEmpty()) : "Empty Reported Route Object.";
+
+               return PCEPRROSubobjectParser.put(((PCEPReportedRouteObject) obj).getSubobjects());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPRequestParameterObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPRequestParameterObjectParser.java
new file mode 100644 (file)
index 0000000..aa5f27a
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject
+ * PCEPRequestParameterObject}
+ */
+
+public class PCEPRequestParameterObjectParser implements PCEPObjectParser {
+
+       /*
+        * lengths of fields in bytes
+        */
+       public static final int FLAGS_PRI_MF_LENGTH = 4; //multi-field
+       public static final int RID_F_LENGTH = 4;
+
+       /*
+        * lengths of subfields inside multi-field in bits
+        */
+       public static final int FLAGS_SF_LENGTH = 29;
+       public static final int PRI_SF_LENGTH = 3;
+
+       /*
+        * offsets of field in bytes
+        */
+
+       public static final int FLAGS_PRI_MF_OFFSET = 0;
+       public static final int RID_F_OFFSET = FLAGS_PRI_MF_OFFSET + FLAGS_PRI_MF_LENGTH;
+       public static final int TLVS_OFFSET = RID_F_OFFSET + RID_F_LENGTH;
+
+       /*
+        * offsets of subfields inside multi-field in bits
+        */
+
+       public static final int FLAGS_SF_OFFSET = 0;
+       public static final int PRI_SF_OFFSET = FLAGS_SF_OFFSET + FLAGS_SF_LENGTH;
+
+       /*
+        * flags offsets inside flags sub-field in bits
+        */
+
+       private static final int O_FLAG_OFFSET = 26;
+       private static final int B_FLAG_OFFSET = 27;
+       private static final int R_FLAG_OFFSET = 28;
+
+       /*
+        * GCO extension flags offsets inside flags sub-field in bits
+        */
+       private static final int M_FLAG_OFFSET = 21;
+       private static final int D_FLAG_OFFSET = 22;
+
+       /*
+        * OF extension flags offsets inside flags sub.field in bits
+        */
+
+       private static int S_FLAG_OFFSET = 24; //Supply OF on response
+
+       /*
+        * RFC6006 flags
+        */
+       private static int F_FLAG_OFFSET = 18;
+
+       private static int N_FLAG_OFFSET = 19;
+
+       private static int E_FLAG_OFFSET = 20;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+               if (bytes.length < TLVS_OFFSET)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+               final BitSet flags = ByteArray.bytesToBitSet(Arrays.copyOfRange(bytes, FLAGS_PRI_MF_OFFSET, FLAGS_PRI_MF_OFFSET + FLAGS_PRI_MF_LENGTH));
+               short priority = 0;
+               priority |= flags.get(PRI_SF_OFFSET + 2) ? 1 : 0;
+               priority |= (flags.get(PRI_SF_OFFSET + 1) ? 1 : 0) << 1;
+               priority |= (flags.get(PRI_SF_OFFSET) ? 1 : 0) << 2;
+
+               return new PCEPRequestParameterObject(flags.get(O_FLAG_OFFSET), flags.get(B_FLAG_OFFSET), flags.get(R_FLAG_OFFSET), flags.get(M_FLAG_OFFSET),
+                               flags.get(D_FLAG_OFFSET), flags.get(S_FLAG_OFFSET), flags.get(F_FLAG_OFFSET), flags.get(N_FLAG_OFFSET), flags.get(E_FLAG_OFFSET), priority,
+                               ByteArray.bytesToLong(Arrays.copyOfRange(bytes, RID_F_OFFSET, RID_F_OFFSET + RID_F_LENGTH)), PCEPTlvParser.parse(ByteArray.cutBytes(bytes,
+                                               TLVS_OFFSET)), processed, ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPRequestParameterObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPRequestParameterObject.");
+
+               final PCEPRequestParameterObject rPObj = (PCEPRequestParameterObject) obj;
+
+               final BitSet flags_priority = new BitSet(FLAGS_PRI_MF_LENGTH * Byte.SIZE);
+
+               flags_priority.set(R_FLAG_OFFSET, rPObj.isReoptimized());
+               flags_priority.set(B_FLAG_OFFSET, rPObj.isBidirectional());
+               flags_priority.set(O_FLAG_OFFSET, rPObj.isLoose());
+               flags_priority.set(M_FLAG_OFFSET, rPObj.isMakeBeforeBreak());
+               flags_priority.set(D_FLAG_OFFSET, rPObj.isReportRequestOrder());
+               flags_priority.set(S_FLAG_OFFSET, rPObj.isSuplyOFOnResponse());
+               flags_priority.set(F_FLAG_OFFSET, rPObj.isFragmentation());
+               flags_priority.set(N_FLAG_OFFSET, rPObj.isP2mp());
+               flags_priority.set(E_FLAG_OFFSET, rPObj.isEroCompression());
+
+               flags_priority.set(PRI_SF_OFFSET, (rPObj.getPriority() & 1 << 2) != 0);
+               flags_priority.set(PRI_SF_OFFSET + 1, (rPObj.getPriority() & 1 << 1) != 0);
+               flags_priority.set(PRI_SF_OFFSET + 2, (rPObj.getPriority() & 1) != 0);
+
+               final byte[] tlvs = PCEPTlvParser.put(rPObj.getTlvs());
+               final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length];
+               ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+               ByteArray.copyWhole(ByteArray.bitSetToBytes(flags_priority, FLAGS_PRI_MF_LENGTH), retBytes, FLAGS_PRI_MF_OFFSET);
+               ByteArray.copyWhole(ByteArray.subByte(ByteArray.longToBytes(rPObj.getRequestID()), (Long.SIZE / Byte.SIZE) - RID_F_LENGTH, RID_F_LENGTH), retBytes,
+                               RID_F_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPRequestedPathBandwidthObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPRequestedPathBandwidthObjectParser.java
new file mode 100644 (file)
index 0000000..052e052
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject
+ * PCEPRequestedPathBandwidthObject}
+ */
+public class PCEPRequestedPathBandwidthObjectParser implements PCEPObjectParser {
+
+       private static final int BANDWIDTH_F_LENGTH = 4;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (bytes.length != BANDWIDTH_F_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: " + BANDWIDTH_F_LENGTH + ".");
+
+               return new PCEPRequestedPathBandwidthObject(new Bandwidth(ByteArray.bytesToFloat(bytes)), processed, ignored);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPRequestedPathBandwidthObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPRequestedPathBandwidthObject.");
+
+               return ByteArray.floatToBytes((float) ((PCEPRequestedPathBandwidthObject) obj).getBandwidth().getBytesPerSecond());
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPSecondaryExplicitRouteObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPSecondaryExplicitRouteObjectParser.java
new file mode 100644 (file)
index 0000000..0da65ec
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPEROSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryExplicitRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+public class PCEPSecondaryExplicitRouteObjectParser implements PCEPObjectParser {
+
+    @Override
+    public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+       if (bytes == null || bytes.length == 0)
+           throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+       final List<ExplicitRouteSubobject> subobjects = PCEPEROSubobjectParser.parse(bytes);
+       if (subobjects.isEmpty())
+           throw new PCEPDeserializerException("Empty Secondary Explicit Route Object.");
+
+       return new PCEPSecondaryExplicitRouteObject(subobjects, processed, ignored);
+    }
+
+    @Override
+    public byte[] put(PCEPObject obj) {
+       if (!(obj instanceof PCEPSecondaryExplicitRouteObject))
+           throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPSecondaryExplicitRouteObject.");
+
+       assert !(((PCEPSecondaryExplicitRouteObject) obj).getSubobjects().isEmpty()) : "Empty Secondary Explicit Route Object.";
+
+       return PCEPEROSubobjectParser.put(((PCEPSecondaryExplicitRouteObject) obj).getSubobjects());
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPSecondaryRecordRouteObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPSecondaryRecordRouteObjectParser.java
new file mode 100644 (file)
index 0000000..523a61d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPRROSubobjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryRecordRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+
+public class PCEPSecondaryRecordRouteObjectParser implements PCEPObjectParser {
+
+    @Override
+    public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+       if (bytes == null || bytes.length == 0)
+           throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+       final List<ReportedRouteSubobject> subobjects = PCEPRROSubobjectParser.parse(bytes);
+       if (subobjects.isEmpty())
+           throw new PCEPDeserializerException("Empty Secondary Recorded Route Object.");
+
+       return new PCEPSecondaryRecordRouteObject(subobjects, processed, ignored);
+    }
+
+    @Override
+    public byte[] put(PCEPObject obj) {
+
+       if (!(obj instanceof PCEPSecondaryRecordRouteObject))
+           throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPSecondaryRecordRouteObject.");
+
+       assert !(((PCEPSecondaryRecordRouteObject) obj).getSubobjects().isEmpty()) : "Empty Secondary Record Route Object.";
+
+       return PCEPRROSubobjectParser.put(((PCEPSecondaryRecordRouteObject) obj).getSubobjects());
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPSvecObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPSvecObjectParser.java
new file mode 100644 (file)
index 0000000..863fd8c
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPSvecObject PCEPSvecObject}
+ */
+public class PCEPSvecObjectParser implements PCEPObjectParser {
+
+       /*
+        * field lengths in bytes
+        */
+       public static final int FLAGS_F_LENGTH = 3;
+       public static final int REQ_LIST_ITEM_LENGTH = 4;
+
+       /*
+        * fields offsets in bytes
+        */
+       public static final int FLAGS_F_OFFSET = 1; // aded reserved field of size 1
+       public static final int REQ_ID_LIST_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+
+       /*
+        * flags offsets inside flags field in bits
+        */
+       public static final int S_FLAG_OFFSET = 21;
+       public static final int N_FLAG_OFFSET = 22;
+       public static final int L_FLAG_OFFSET = 23;
+
+       public static final int P_FLAG_OFFSET = 19;
+       public static final int D_FLAG_OFFSET = 20;
+
+       /*
+        * min size in bytes
+        */
+
+       public static final int MIN_SIZE = FLAGS_F_LENGTH + FLAGS_F_OFFSET;
+
+       @Override
+       public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+               if (bytes == null || bytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+               if (bytes.length < MIN_SIZE)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + MIN_SIZE + ".");
+
+               final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(bytes, FLAGS_F_OFFSET, FLAGS_F_LENGTH));
+               final int numOfRIDs = (bytes.length - FLAGS_F_LENGTH - FLAGS_F_OFFSET) / REQ_LIST_ITEM_LENGTH;
+               final List<Long> requestIDs = new ArrayList<Long>(numOfRIDs);
+
+               for (int i = REQ_ID_LIST_OFFSET; i < bytes.length; i += REQ_LIST_ITEM_LENGTH) {
+                       requestIDs.add(UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(bytes, i, REQ_LIST_ITEM_LENGTH))));
+               }
+
+               if (requestIDs.isEmpty())
+                       throw new PCEPDeserializerException("Empty Svec Object - no request ids.");
+
+               return new PCEPSvecObject(flags.get(L_FLAG_OFFSET), flags.get(N_FLAG_OFFSET), flags.get(S_FLAG_OFFSET), flags.get(P_FLAG_OFFSET),
+                               flags.get(D_FLAG_OFFSET), requestIDs, processed);
+       }
+
+       @Override
+       public byte[] put(PCEPObject obj) {
+               if (!(obj instanceof PCEPSvecObject))
+                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPSvecObject.");
+
+               final PCEPSvecObject svecObj = (PCEPSvecObject) obj;
+               final byte[] retBytes = new byte[svecObj.getRequestIDs().size() * REQ_LIST_ITEM_LENGTH + REQ_ID_LIST_OFFSET];
+               final List<Long> requestIDs = svecObj.getRequestIDs();
+               final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+               flags.set(L_FLAG_OFFSET, svecObj.isLinkDiversed());
+               flags.set(N_FLAG_OFFSET, svecObj.isNodeDiversed());
+               flags.set(S_FLAG_OFFSET, svecObj.isSrlgDiversed());
+               flags.set(P_FLAG_OFFSET, svecObj.isParitialPathDiversed());
+               flags.set(D_FLAG_OFFSET, svecObj.isLinkDirectionDiversed());
+
+               ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+               for (int i = 0; i < requestIDs.size(); i++) {
+                       System.arraycopy(ByteArray.longToBytes(requestIDs.get(i)), 4, retBytes, REQ_LIST_ITEM_LENGTH * i + REQ_ID_LIST_OFFSET, REQ_LIST_ITEM_LENGTH);
+               }
+
+               assert !(requestIDs.isEmpty()) : "Empty Svec Object - no request ids.";
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPUnreachedIPv4DestinationObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPUnreachedIPv4DestinationObjectParser.java
new file mode 100644 (file)
index 0000000..d0bed45
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.Util;
+import org.opendaylight.protocol.pcep.object.PCEPUnreachedDestinationObject;
+
+public class PCEPUnreachedIPv4DestinationObjectParser implements PCEPObjectParser {
+
+    /*
+     * fields lengths and offsets for IPv4 in bytes
+     */
+    public static final int DEST4_F_LENGTH = 4;
+
+    public static final int DEST4_F_OFFSET = 0;
+
+    @Override
+    public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+       if (bytes == null)
+           throw new IllegalArgumentException("Array of bytes is mandatory");
+
+       return new PCEPUnreachedDestinationObject<IPv4Address>(Util.parseAddresses(bytes, DEST4_F_OFFSET, IPv4.FAMILY, DEST4_F_LENGTH), processed, ignored);
+    }
+
+    @Override
+    public byte[] put(PCEPObject obj) {
+       if (!(obj instanceof PCEPUnreachedDestinationObject))
+           throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPUnreachedDestinationObject.");
+
+       final PCEPUnreachedDestinationObject<?> uDObj = (PCEPUnreachedDestinationObject<?>) obj;
+
+       if (uDObj.getUnreachedDestinations().isEmpty())
+           return new byte[0];
+
+       if (!(uDObj.getUnreachedDestinations().get(0) instanceof IPv4Address))
+           throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + uDObj.getUnreachedDestinations().get(0).getClass()
+                   + ". Needed IPv4Address");
+
+       final byte[] retBytes = new byte[DEST4_F_LENGTH * uDObj.getUnreachedDestinations().size()];
+       Util.putAddresses(retBytes, DEST4_F_OFFSET, uDObj.getUnreachedDestinations(), DEST4_F_LENGTH);
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPUnreachedIPv6DestinationObjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/PCEPUnreachedIPv6DestinationObjectParser.java
new file mode 100644 (file)
index 0000000..77e7c8d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.Util;
+import org.opendaylight.protocol.pcep.object.PCEPUnreachedDestinationObject;
+
+public class PCEPUnreachedIPv6DestinationObjectParser implements PCEPObjectParser {
+
+    /*
+     * fields lengths and offsets for IPv6 in bytes
+     */
+    public static final int DEST6_F_LENGTH = 16;
+
+    public static final int DEST6_F_OFFSET = 0;
+
+    @Override
+    public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+       if (bytes == null)
+           throw new IllegalArgumentException("Array of bytes is mandatory");
+
+       return new PCEPUnreachedDestinationObject<IPv6Address>(Util.parseAddresses(bytes, DEST6_F_OFFSET, IPv6.FAMILY, DEST6_F_LENGTH), processed, ignored);
+    }
+
+    @Override
+    public byte[] put(PCEPObject obj) {
+       if (!(obj instanceof PCEPUnreachedDestinationObject))
+           throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPUnreachedDestinationObject.");
+
+       final PCEPUnreachedDestinationObject<?> uDObj = (PCEPUnreachedDestinationObject<?>) obj;
+
+       if (uDObj.getUnreachedDestinations().isEmpty())
+           return new byte[0];
+
+       if (!(uDObj.getUnreachedDestinations().get(0) instanceof IPv6Address))
+           throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + uDObj.getUnreachedDestinations().get(0).getClass()
+                   + ". Needed IPv6Address");
+
+       final byte[] retBytes = new byte[DEST6_F_LENGTH * uDObj.getUnreachedDestinations().size()];
+       Util.putAddresses(retBytes, DEST6_F_OFFSET, uDObj.getUnreachedDestinations(), DEST6_F_LENGTH);
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/UnknownObject.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/object/UnknownObject.java
new file mode 100644 (file)
index 0000000..f47e627
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.object;
+
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+public class UnknownObject extends PCEPObject {
+
+       private final PCEPErrors error;
+
+       public UnknownObject(boolean processed, boolean ignored, PCEPErrors error) {
+               super(processed, ignored);
+
+               this.error = error;
+       }
+
+       public PCEPErrors getError() {
+               return this.error;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROAsNumberSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROAsNumberSubobjectParser.java
new file mode 100644 (file)
index 0000000..580232b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject
+ * EROAsNumberSubobject}
+ */
+
+public class EROAsNumberSubobjectParser {
+       public static final int AS_NUMBER_LENGTH = 2;
+
+       public static final int AS_NUMBER_OFFSET = 0;
+
+       public static final int CONTENT_LENGTH = AS_NUMBER_LENGTH + AS_NUMBER_OFFSET;
+
+       public static EROAsNumberSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               return new EROAsNumberSubobject(new ASNumber((ByteArray.bytesToShort(soContentsBytes) & 0xFFFF)), loose);
+       }
+
+       public static byte[] put(ExplicitRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof EROAsNumberSubobject))
+                       throw new IllegalArgumentException("Unknown ExplicitRouteSubobject instance. Passed " + objToSerialize.getClass()
+                                       + ". Needed EROAsNumberSubobject.");
+
+               final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+               System.arraycopy(ByteArray.longToBytes(((EROAsNumberSubobject) objToSerialize).getASNumber().getAsn()), Long.SIZE / Byte.SIZE - AS_NUMBER_LENGTH,
+                               retBytes, AS_NUMBER_OFFSET, AS_NUMBER_LENGTH);
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROExplicitExclusionRouteSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROExplicitExclusionRouteSubobjectParser.java
new file mode 100644 (file)
index 0000000..0a2ad69
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.PCEPXROSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.EROExplicitExclusionRouteSubobject;
+
+public class EROExplicitExclusionRouteSubobjectParser {
+    public static EROExplicitExclusionRouteSubobject parse(byte[] cutBytes, boolean loose) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+       return new EROExplicitExclusionRouteSubobject(PCEPXROSubobjectParser.parse(cutBytes));
+    }
+
+    public static byte[] put(EROExplicitExclusionRouteSubobject objToSerialize) {
+       return PCEPXROSubobjectParser.put(objToSerialize.getXroSubobjets());
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROGeneralizedLabelSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROGeneralizedLabelSubobjectParser.java
new file mode 100644 (file)
index 0000000..4f6d17c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+
+public class EROGeneralizedLabelSubobjectParser implements EROLabelParser {
+
+    @Override
+    public EROLabelSubobject parse(byte[] cutBytes, boolean upStream, boolean loose) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+       return new EROGeneralizedLabelSubobject(cutBytes, upStream, loose);
+    }
+
+    @Override
+    public byte[] put(EROLabelSubobject objToSerialize) {
+       if (!(objToSerialize instanceof EROGeneralizedLabelSubobject))
+           throw new IllegalArgumentException("Unknown EROLabelSubobject instance. Passed " + objToSerialize.getClass()
+                   + ". Needed EROGeneralizedLabelSubobject.");
+       final byte[] retBytes = ((EROGeneralizedLabelSubobject) objToSerialize).getLabel();
+
+       return retBytes;
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROIPv4PrefixSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROIPv4PrefixSubobjectParser.java
new file mode 100644 (file)
index 0000000..cb063cc
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject
+ * EROIPPrefixSubobject<IPv4Prefix>}
+ */
+public class EROIPv4PrefixSubobjectParser {
+       public static final int IP_F_LENGTH = 4;
+       public static final int PREFIX_F_LENGTH = 1;
+
+       public static final int IP_F_OFFSET = 0;
+       public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+
+       public static final int CONTENT_LENGTH = PREFIX_F_OFFSET + PREFIX_F_LENGTH + 1; //added reserved field of size 1 byte
+
+       public static EROIPPrefixSubobject<IPv4Prefix> parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               final IPv4Address address = new IPv4Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+               final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+               return new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(address, length), loose);
+       }
+
+       public static byte[] put(ExplicitRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof EROIPPrefixSubobject))
+                       throw new IllegalArgumentException("Unknown ExplicitRouteSubobject instance. Passed " + objToSerialize.getClass()
+                                       + ". Needed EROIPPrefixSubobject.");
+
+               final EROIPPrefixSubobject<?> specObj = (EROIPPrefixSubobject<?>) objToSerialize;
+               final Prefix<?> prefix = specObj.getPrefix();
+
+               if (!(prefix instanceof IPv4Prefix))
+                       throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv4Prefix.");
+
+               final byte[] retBytes = new byte[CONTENT_LENGTH];
+               ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+               retBytes[PREFIX_F_OFFSET] = ByteArray.intToBytes(prefix.getLength())[Integer.SIZE / Byte.SIZE - 1];
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROIPv6PrefixSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROIPv6PrefixSubobjectParser.java
new file mode 100644 (file)
index 0000000..869ee28
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject
+ * EROIPPrefixSubobject<IPv6Prefix>}
+ */
+public class EROIPv6PrefixSubobjectParser {
+       public static final int IP_F_LENGTH = 16;
+       public static final int PREFIX_F_LENGTH = 1;
+
+       public static final int IP_F_OFFSET = 0;
+       public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+
+       public static final int CONTENT_LENGTH = PREFIX_F_OFFSET + PREFIX_F_LENGTH + 1; // added reserved field of size 1 byte
+
+       public static EROIPPrefixSubobject<IPv6Prefix> parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               final IPv6Address address = new IPv6Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+               final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+               return new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(address, length), loose);
+       }
+
+       public static byte[] put(ExplicitRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof EROIPPrefixSubobject))
+                       throw new IllegalArgumentException("Unknown ExplicitRouteSubobject instance. Passed " + objToSerialize.getClass()
+                                       + ". Needed EROIPPrefixSubobject.");
+
+               final EROIPPrefixSubobject<?> specObj = (EROIPPrefixSubobject<?>) objToSerialize;
+               final Prefix<?> prefix = specObj.getPrefix();
+
+               if (!(prefix instanceof IPv6Prefix))
+                       throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv6Prefix.");
+
+               final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+               ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+               retBytes[PREFIX_F_OFFSET] = ByteArray.intToBytes(prefix.getLength())[Integer.SIZE / Byte.SIZE - 1];
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROLabelParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROLabelParser.java
new file mode 100644 (file)
index 0000000..b70d7de
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+
+public interface EROLabelParser {
+
+    EROLabelSubobject parse(byte[] cutBytes, boolean upStream, boolean loose) throws PCEPDeserializerException;
+
+    byte[] put(EROLabelSubobject objToSerialize);
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROLabelSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROLabelSubobjectParser.java
new file mode 100644 (file)
index 0000000..1bc9e61
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.Util.BiParsersMap;
+import org.opendaylight.protocol.pcep.subobject.EROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROType1LabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROLabelSubobjectParser {
+
+    public static final int RES_F_LENGTH = 1;
+
+    public static final int C_TYPE_F_LENGTH = 1;
+
+    public static final int RES_F_OFFSET = 0;
+
+    public static final int C_TYPE_F_OFFSET = RES_F_OFFSET + RES_F_LENGTH;
+
+    public static final int HEADER_LENGTH = C_TYPE_F_OFFSET + C_TYPE_F_LENGTH;
+
+    public static final int U_FLAG_OFFSET = 0;
+
+    private static class MapOfParsers extends BiParsersMap<Class<? extends EROLabelSubobject>, Integer, EROLabelParser> {
+       private final static MapOfParsers instance = new MapOfParsers();
+
+       private MapOfParsers() {
+           this.fillInMap();
+       }
+
+       private void fillInMap() {
+           this.put(EROType1LabelSubobject.class, 1, new EROType1LabelSubobjectParser());
+           this.put(EROGeneralizedLabelSubobject.class, 2, new EROGeneralizedLabelSubobjectParser());
+           this.put(EROWavebandSwitchingLabelSubobject.class, 3, new EROWavebandSwitchingLabelSubobjectParser());
+       }
+
+       public static MapOfParsers getInstance() {
+           return instance;
+       }
+    }
+
+    public static EROLabelSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length < HEADER_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + HEADER_LENGTH + ".");
+
+       final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(soContentsBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+       final int c_type = soContentsBytes[C_TYPE_F_OFFSET] & 0xFF;
+
+       final EROLabelParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+       if (parser == null) {
+           throw new PCEPDeserializerException("Unknown C-TYPE for ero label subobject. Passed: " + c_type);
+       }
+
+       return parser.parse(ByteArray.cutBytes(soContentsBytes, HEADER_LENGTH), reserved.get(U_FLAG_OFFSET), loose);
+    }
+
+    public static byte[] put(EROLabelSubobject objToSerialize) {
+       final Integer c_type = MapOfParsers.getInstance().getKeyValueFromKey(objToSerialize.getClass());
+       final EROLabelParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+       if (c_type == null || parser == null)
+           throw new IllegalArgumentException("Unknown EROLabelSubobject instance. Passed " + objToSerialize.getClass());
+
+       final byte[] labelbytes = parser.put(objToSerialize);
+
+       final byte[] retBytes = new byte[labelbytes.length + HEADER_LENGTH];
+
+       System.arraycopy(labelbytes, 0, retBytes, HEADER_LENGTH, labelbytes.length);
+
+       final BitSet reserved = new BitSet();
+       reserved.set(U_FLAG_OFFSET, objToSerialize.isUpStream());
+       System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+       retBytes[C_TYPE_F_OFFSET] = (byte) c_type.intValue();
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROPathKeyWith128PCEIDSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROPathKeyWith128PCEIDSubobjectParser.java
new file mode 100644 (file)
index 0000000..8c8bd43
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROPathKeyWith128PCEIDSubobjectParser {
+
+    public static final int PK_F_LENGTH = 2;
+    public static final int PCE_ID_F_LENGTH = 16;
+
+    public static final int PK_F_OFFSET = 0;
+    public static final int PCE_ID_F_OFFSET = PK_F_OFFSET + PK_F_LENGTH;
+
+    public static final int CONTENT_LENGTH = PCE_ID_F_OFFSET + PCE_ID_F_LENGTH;
+
+    public static EROPathKeyWith128PCEIDSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length != CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+       final int pathKey = ByteArray.bytesToShort(Arrays.copyOfRange(soContentsBytes, PK_F_OFFSET, PCE_ID_F_OFFSET)) & 0xFFFF;
+
+       final byte[] pceId = Arrays.copyOfRange(soContentsBytes, PCE_ID_F_OFFSET, CONTENT_LENGTH);
+
+       return new EROPathKeyWith128PCEIDSubobject(pathKey, pceId, loose);
+    }
+
+    public static byte[] put(EROPathKeyWith128PCEIDSubobject objToSerialize) {
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+       System.arraycopy(ByteArray.shortToBytes((short) objToSerialize.getPathKey()), 0, retBytes, PK_F_OFFSET, PK_F_LENGTH);
+
+       if (objToSerialize.getPceId().length != PCE_ID_F_LENGTH)
+           throw new IllegalArgumentException("Wrong length of pce id. Passed: " + objToSerialize.getPceId().length + ". Expected: =" + PCE_ID_F_LENGTH);
+       System.arraycopy(objToSerialize.getPceId(), 0, retBytes, PCE_ID_F_OFFSET, PCE_ID_F_LENGTH);
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROPathKeyWith32PCEIDSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROPathKeyWith32PCEIDSubobjectParser.java
new file mode 100644 (file)
index 0000000..ffbb7da
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROPathKeyWith32PCEIDSubobjectParser {
+
+    public static final int PK_F_LENGTH = 2;
+    public static final int PCE_ID_F_LENGTH = 4;
+
+    public static final int PK_F_OFFSET = 0;
+    public static final int PCE_ID_F_OFFSET = PK_F_OFFSET + PK_F_LENGTH;
+
+    public static final int CONTENT_LENGTH = PCE_ID_F_OFFSET + PCE_ID_F_LENGTH;
+
+    public static EROPathKeyWith32PCEIDSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length != CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+       final int pathKey = ByteArray.bytesToShort(Arrays.copyOfRange(soContentsBytes, PK_F_OFFSET, PCE_ID_F_OFFSET)) & 0xFFFF;
+
+       final byte[] pceId = Arrays.copyOfRange(soContentsBytes, PCE_ID_F_OFFSET, CONTENT_LENGTH);
+
+       return new EROPathKeyWith32PCEIDSubobject(pathKey, pceId, loose);
+    }
+
+    public static byte[] put(EROPathKeyWith32PCEIDSubobject objToSerialize) {
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+       System.arraycopy(ByteArray.shortToBytes((short) objToSerialize.getPathKey()), 0, retBytes, PK_F_OFFSET, PK_F_LENGTH);
+
+       if (objToSerialize.getPceId().length != PCE_ID_F_LENGTH)
+           throw new IllegalArgumentException("Wrong length of pce id. Passed: " + objToSerialize.getPceId().length + ". Expected: =" + PCE_ID_F_LENGTH);
+       System.arraycopy(objToSerialize.getPceId(), 0, retBytes, PCE_ID_F_OFFSET, PCE_ID_F_LENGTH);
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionParser.java
new file mode 100644 (file)
index 0000000..1b0c8d9
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
+
+public interface EROProtectionParser {
+
+    EROProtectionSubobject parse(byte[] cutBytes, boolean loose) throws PCEPDeserializerException;
+
+    byte[] put(EROProtectionSubobject objToSerialize);
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionSubobjectParser.java
new file mode 100644 (file)
index 0000000..8cb8bbf
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.Util.BiParsersMap;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType1Subobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType2Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROProtectionSubobjectParser {
+
+    public static final int RES_F_LENGTH = 1;
+
+    public static final int C_TYPE_F_LENGTH = 1;
+
+    public static final int RES_F_OFFSET = 0;
+
+    public static final int C_TYPE_F_OFFSET = RES_F_OFFSET + RES_F_LENGTH;
+
+    public static final int HEADER_LENGTH = C_TYPE_F_OFFSET + C_TYPE_F_LENGTH;
+
+    public static final int U_FLAG_OFFSET = 0;
+
+    private static class MapOfParsers extends BiParsersMap<Class<? extends EROProtectionSubobject>, Integer, EROProtectionParser> {
+       private final static MapOfParsers instance = new MapOfParsers();
+
+       private MapOfParsers() {
+           this.fillInMap();
+       }
+
+       private void fillInMap() {
+           this.put(EROProtectionType1Subobject.class, 1, new EROProtectionType1SubobjectParser());
+           this.put(EROProtectionType2Subobject.class, 2, new EROProtectionType2SubobjectParser());
+       }
+
+       public static MapOfParsers getInstance() {
+           return instance;
+       }
+    }
+
+    public static EROProtectionSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length < HEADER_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + HEADER_LENGTH + ".");
+
+       final int c_type = soContentsBytes[C_TYPE_F_OFFSET] & 0xFF;
+
+       final EROProtectionParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+       if (parser == null) {
+           throw new PCEPDeserializerException("Unknown C-TYPE for ero protection subobject. Passed: " + c_type);
+       }
+
+       return parser.parse(ByteArray.cutBytes(soContentsBytes, HEADER_LENGTH), loose);
+    }
+
+    public static byte[] put(EROProtectionSubobject objToSerialize) {
+       final Integer c_type = MapOfParsers.getInstance().getKeyValueFromKey(objToSerialize.getClass());
+       final EROProtectionParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+       if (c_type == null || parser == null)
+           throw new IllegalArgumentException("Unknown EROProtectionSubobject instance. Passed " + objToSerialize.getClass());
+
+       final byte[] protBytes = parser.put(objToSerialize);
+
+       final byte[] retBytes = new byte[protBytes.length + HEADER_LENGTH];
+
+       System.arraycopy(protBytes, 0, retBytes, HEADER_LENGTH, protBytes.length);
+
+       retBytes[C_TYPE_F_OFFSET] = (byte) c_type.intValue();
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionType1SubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionType1SubobjectParser.java
new file mode 100644 (file)
index 0000000..f9326a0
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType1Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROProtectionType1SubobjectParser implements EROProtectionParser {
+
+    public static final int RES_F_LENGTH = 4;
+
+    public static final int RES_F_OFFSET = 0;
+
+    public static final int CONTENT_LENGTH = RES_F_OFFSET + RES_F_LENGTH;
+
+    /*
+     * offsets of flags inside reserved field
+     */
+    public static final int S_FLAG_OFFSET = 0;
+
+    @Override
+    public EROProtectionSubobject parse(byte[] cutBytes, boolean loose) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (cutBytes.length < CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+       final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(cutBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+       final byte linkFlags = (byte) (cutBytes[3] & 0x3F);
+
+       return new EROProtectionType1Subobject(reserved.get(S_FLAG_OFFSET), linkFlags, loose);
+    }
+
+    @Override
+    public byte[] put(EROProtectionSubobject objToSerialize) {
+       if (!(objToSerialize instanceof EROProtectionType1Subobject))
+           throw new IllegalArgumentException("Unknown EROProtectionSubobject instance. Passed " + objToSerialize.getClass()
+                   + ". Needed EROProtectionType1Subobject.");
+
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+       final BitSet reserved = new BitSet();
+       reserved.set(S_FLAG_OFFSET, ((EROProtectionType1Subobject) objToSerialize).isSecondary());
+       System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+       retBytes[3] |= ((EROProtectionType1Subobject) objToSerialize).getLinkFlags() & 0x3F;
+
+       return retBytes;
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionType2SubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROProtectionType2SubobjectParser.java
new file mode 100644 (file)
index 0000000..33e034c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType2Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROProtectionType2SubobjectParser implements EROProtectionParser {
+
+    public static final int RES_F_LENGTH = 8;
+
+    public static final int RES_F_OFFSET = 0;
+
+    public static final int CONTENT_LENGTH = RES_F_OFFSET + RES_F_LENGTH;
+
+    /*
+     * offsets of flags inside reserved field
+     */
+    public static final int S_FLAG_OFFSET = 0;
+    public static final int P_FLAG_OFFSET = 1;
+    public static final int N_FLAG_OFFSET = 2;
+    public static final int O_FLAG_OFFSET = 3;
+
+    public static final int I_FLAG_OFFSET = 32;
+    public static final int R_FLAG_OFFSET = 33;
+
+    @Override
+    public EROProtectionSubobject parse(byte[] cutBytes, boolean loose) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (cutBytes.length < CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+       final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(cutBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+       final byte linkFlags = (byte) (cutBytes[3] & 0x3F);
+       final byte lspFlags = (byte) (cutBytes[1] & 0x3F);
+       final byte segFlags = (byte) (cutBytes[5] & 0x3F);
+
+       return new EROProtectionType2Subobject(reserved.get(S_FLAG_OFFSET), reserved.get(P_FLAG_OFFSET), reserved.get(N_FLAG_OFFSET),
+               reserved.get(N_FLAG_OFFSET), lspFlags, linkFlags, reserved.get(I_FLAG_OFFSET), reserved.get(R_FLAG_OFFSET), segFlags, loose);
+    }
+
+    @Override
+    public byte[] put(EROProtectionSubobject objToSerialize) {
+       if (!(objToSerialize instanceof EROProtectionType2Subobject))
+           throw new IllegalArgumentException("Unknown EROProtectionSubobject instance. Passed " + objToSerialize.getClass()
+                   + ". Needed EROProtectionType2Subobject.");
+
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+       final BitSet reserved = new BitSet();
+       reserved.set(S_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isSecondaryLsp());
+       reserved.set(P_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isProtectionLsp());
+       reserved.set(N_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isNotification());
+       reserved.set(O_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isOperational());
+       reserved.set(I_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isInPlace());
+       reserved.set(R_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isRequired());
+       System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+       retBytes[3] |= ((EROProtectionType2Subobject) objToSerialize).getLinkFlags() & 0x3F;
+       retBytes[1] |= ((EROProtectionType2Subobject) objToSerialize).getLspFlags() & 0x3F;
+       retBytes[5] |= ((EROProtectionType2Subobject) objToSerialize).getSegFlags() & 0x3F;
+
+       return retBytes;
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROType1LabelSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROType1LabelSubobjectParser.java
new file mode 100644 (file)
index 0000000..344d9bc
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROType1LabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+public class EROType1LabelSubobjectParser implements EROLabelParser {
+
+    public static final int LABEL_LENGTH = 4;
+
+    @Override
+    public EROLabelSubobject parse(byte[] cutBytes, boolean upStream, boolean loose) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (cutBytes.length != LABEL_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: " + LABEL_LENGTH + ".");
+
+       return new EROType1LabelSubobject(UnsignedInts.toLong(ByteArray.bytesToInt(cutBytes)), upStream, loose);
+    }
+
+    @Override
+    public byte[] put(EROLabelSubobject objToSerialize) {
+       if (!(objToSerialize instanceof EROType1LabelSubobject))
+           throw new IllegalArgumentException("Unknown EROLabelSubobject instance. Passed " + objToSerialize.getClass() + ". Needed EROType1LabelSubobject.");
+
+       return ByteArray.intToBytes((int) ((EROType1LabelSubobject) objToSerialize).getLabel());
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROUnnumberedInterfaceSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROUnnumberedInterfaceSubobjectParser.java
new file mode 100644 (file)
index 0000000..81dfec0
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for
+ * {@link org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject
+ * EROUnnumberedInterfaceSubobject}
+ */
+public class EROUnnumberedInterfaceSubobjectParser {
+       public static final int ROUTER_ID_NUMBER_LENGTH = 4;
+       public static final int INTERFACE_ID_NUMBER_LENGTH = 4;
+
+       public static final int ROUTER_ID_NUMBER_OFFSET = 2; // added reserved field of size 2
+       public static final int INTERFACE_ID_NUMBER_OFFSET = ROUTER_ID_NUMBER_OFFSET + ROUTER_ID_NUMBER_LENGTH;
+
+       public static final int CONTENT_LENGTH = INTERFACE_ID_NUMBER_OFFSET + INTERFACE_ID_NUMBER_LENGTH;
+
+       public static EROUnnumberedInterfaceSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               return new EROUnnumberedInterfaceSubobject(new IPv4Address(ByteArray.subByte(soContentsBytes, ROUTER_ID_NUMBER_OFFSET, ROUTER_ID_NUMBER_LENGTH)), new UnnumberedInterfaceIdentifier(
+                               UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(soContentsBytes, INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH)))), loose);
+       }
+
+       public static byte[] put(ExplicitRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof EROUnnumberedInterfaceSubobject))
+                       throw new IllegalArgumentException("Unknown ExplicitRouteSubobject instance. Passed " + objToSerialize.getClass()
+                                       + ". Needed EROUnnumberedInterfaceSubobject.");
+
+               byte[] retBytes;
+               retBytes = new byte[CONTENT_LENGTH];
+               final EROUnnumberedInterfaceSubobject specObj = (EROUnnumberedInterfaceSubobject) objToSerialize;
+
+               ByteArray.copyWhole(specObj.getRouterID().getAddress(), retBytes, ROUTER_ID_NUMBER_OFFSET);
+               System.arraycopy(ByteArray.longToBytes(specObj.getInterfaceID().getInterfaceId()), Long.SIZE / Byte.SIZE - INTERFACE_ID_NUMBER_LENGTH, retBytes,
+                               INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH);
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROWavebandSwitchingLabelSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/EROWavebandSwitchingLabelSubobjectParser.java
new file mode 100644 (file)
index 0000000..c93a63e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+public class EROWavebandSwitchingLabelSubobjectParser implements EROLabelParser {
+
+    public static int WAVEB_F_LENGTH = 4;
+    public static int START_F_LENGTH = 4;
+    public static int END_F_LENGTH = 4;
+
+    public static int WAVEB_F_OFFSET = 0;
+    public static int START_F_OFFSET = WAVEB_F_OFFSET + WAVEB_F_LENGTH;
+    public static int END_F_OFFSET = START_F_OFFSET + START_F_LENGTH;
+
+    public static int CONTENT_LENGTH = END_F_OFFSET + END_F_LENGTH;
+
+    @Override
+    public EROLabelSubobject parse(byte[] cutBytes, boolean upStream, boolean loose) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+       if (cutBytes.length != CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+       return new EROWavebandSwitchingLabelSubobject(UnsignedInts.toLong(ByteArray.bytesToInt(Arrays.copyOfRange(cutBytes, WAVEB_F_OFFSET, START_F_OFFSET))),
+               UnsignedInts.toLong(ByteArray.bytesToInt(Arrays.copyOfRange(cutBytes, START_F_OFFSET, END_F_OFFSET))), UnsignedInts.toLong(ByteArray
+                       .bytesToInt(Arrays.copyOfRange(cutBytes, END_F_OFFSET, CONTENT_LENGTH))), upStream, loose);
+    }
+
+    @Override
+    public byte[] put(EROLabelSubobject objToSerialize) {
+       if (!(objToSerialize instanceof EROWavebandSwitchingLabelSubobject))
+           throw new IllegalArgumentException("Unknown EROLabelSubobject instance. Passed " + objToSerialize.getClass()
+                   + ". Needed EROWavebandSwitchingLabelSubobject.");
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+       final EROWavebandSwitchingLabelSubobject obj = (EROWavebandSwitchingLabelSubobject) objToSerialize;
+
+       System.arraycopy(ByteArray.intToBytes((int) obj.getWavebandId()), 0, retBytes, WAVEB_F_OFFSET, WAVEB_F_LENGTH);
+       System.arraycopy(ByteArray.intToBytes((int) obj.getStartLabel()), 0, retBytes, START_F_OFFSET, START_F_LENGTH);
+       System.arraycopy(ByteArray.intToBytes((int) obj.getEndLabel()), 0, retBytes, END_F_OFFSET, END_F_LENGTH);
+
+       return retBytes;
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROAsNumberSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROAsNumberSubobjectParser.java
new file mode 100644 (file)
index 0000000..84e3158
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.RROAsNumberSubobject
+ * RROAsNumberSubobject}
+ */
+
+public class RROAsNumberSubobjectParser {
+       public static final int AS_NUMBER_LENGTH = 2;
+
+       public static final int AS_NUMBER_OFFSET = 0;
+
+       public static final int CONTENT_LENGTH = AS_NUMBER_LENGTH + AS_NUMBER_OFFSET;
+
+       public static RROAsNumberSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               return new RROAsNumberSubobject(new ASNumber((ByteArray.bytesToShort(soContentsBytes) & 0xFFFF)));
+       }
+
+       public static byte[] put(ReportedRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof RROAsNumberSubobject))
+                       throw new IllegalArgumentException("Unknown ReportedRouteSubobject instance. Passed " + objToSerialize.getClass()
+                                       + ". Needed RROAsNumberSubobject.");
+
+               final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+               System.arraycopy(ByteArray.longToBytes(((RROAsNumberSubobject) objToSerialize).getASNumber().getAsn()), Long.SIZE / Byte.SIZE - AS_NUMBER_LENGTH,
+                               retBytes, AS_NUMBER_OFFSET, AS_NUMBER_LENGTH);
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROAttributesSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROAttributesSubobjectParser.java
new file mode 100644 (file)
index 0000000..c418a37
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROAttributesSubobject;
+
+public class RROAttributesSubobjectParser {
+
+    public static final int RES_F_LENGTH = 2;
+
+    public static final int RES_F_OFFSET = 0;
+    public static final int ATTRS_F_OFFSET = RES_F_OFFSET + RES_F_LENGTH;
+
+    public static RROAttributesSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length <= RES_F_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + RES_F_LENGTH + ".");
+
+       final byte[] attributes = Arrays.copyOfRange(soContentsBytes, ATTRS_F_OFFSET, soContentsBytes.length);
+
+       return new RROAttributesSubobject(attributes);
+    }
+
+    public static byte[] put(RROAttributesSubobject objToSerialize) {
+       final byte[] retBytes = new byte[RES_F_LENGTH + objToSerialize.getAttributes().length];
+
+       final byte[] attrs = objToSerialize.getAttributes();
+
+       System.arraycopy(attrs, 0, retBytes, ATTRS_F_OFFSET, attrs.length);
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROGeneralizedLabelSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROGeneralizedLabelSubobjectParser.java
new file mode 100644 (file)
index 0000000..2780813
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+
+public class RROGeneralizedLabelSubobjectParser implements RROLabelParser {
+
+    @Override
+    public RROLabelSubobject parse(byte[] cutBytes, boolean upStream) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+       return new RROGeneralizedLabelSubobject(cutBytes, upStream);
+    }
+
+    @Override
+    public byte[] put(RROLabelSubobject objToSerialize) {
+       if (!(objToSerialize instanceof RROGeneralizedLabelSubobject))
+           throw new IllegalArgumentException("Unknown RROLabelSubobject instance. Passed " + objToSerialize.getClass()
+                   + ". Needed RROGeneralizedLabelSubobject.");
+       final byte[] retBytes = ((RROGeneralizedLabelSubobject) objToSerialize).getLabel();
+
+       return retBytes;
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROIPv4AddressSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROIPv4AddressSubobjectParser.java
new file mode 100644 (file)
index 0000000..4563b9d
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject
+ * RROIPAddressSubobject<IPv4Prefix>}
+ */
+public class RROIPv4AddressSubobjectParser {
+    public static final int IP_F_LENGTH = 4;
+    public static final int PREFIX_F_LENGTH = 1;
+    public static final int FLAGS_F_LENGTH = 1;
+
+    public static final int IP_F_OFFSET = 0;
+    public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+    public static final int FLAGS_F_OFFSET = PREFIX_F_OFFSET + PREFIX_F_LENGTH;
+
+    public static final int CONTENT_LENGTH = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+
+    /*
+     * flags offset in bits
+     */
+    public static final int LPA_F_OFFSET = 7;
+    public static final int LPIU_F_OFFSET = 6;
+
+    public static RROIPAddressSubobject<IPv4Prefix> parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length != CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+       final IPv4Address address = new IPv4Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+       final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+       final BitSet flags = ByteArray.bytesToBitSet(Arrays.copyOfRange(soContentsBytes, FLAGS_F_OFFSET, FLAGS_F_OFFSET + FLAGS_F_LENGTH));
+
+       return new RROIPAddressSubobject<IPv4Prefix>(new IPv4Prefix(address, length), flags.get(LPA_F_OFFSET), flags.get(LPIU_F_OFFSET));
+    }
+
+    public static byte[] put(ReportedRouteSubobject objToSerialize) {
+       if (!(objToSerialize instanceof RROIPAddressSubobject))
+           throw new IllegalArgumentException("Unknown ReportedRouteSubobject instance. Passed " + objToSerialize.getClass()
+                   + ". Needed RROIPAddressSubobject.");
+
+       final RROIPAddressSubobject<?> specObj = (RROIPAddressSubobject<?>) objToSerialize;
+       final Prefix<?> prefix = specObj.getPrefix();
+
+       if (!(prefix instanceof IPv4Prefix))
+           throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv4Prefix.");
+
+       final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+
+       flags.set(LPA_F_OFFSET, specObj.isLocalProtectionAvailable());
+       flags.set(LPIU_F_OFFSET, specObj.isLocalProtectionInUse());
+
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+       ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+       retBytes[PREFIX_F_OFFSET] = ByteArray.intToBytes(prefix.getLength())[Integer.SIZE / Byte.SIZE - 1];
+       ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROIPv6AddressSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROIPv6AddressSubobjectParser.java
new file mode 100644 (file)
index 0000000..a118df3
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject
+ * RROIPAddressSubobject<IPv6Prefix>}
+ */
+public class RROIPv6AddressSubobjectParser {
+    public static final int IP_F_LENGTH = 16;
+    public static final int PREFIX_F_LENGTH = 1;
+    public static final int FLAGS_F_LENGTH = 1;
+
+    public static final int IP_F_OFFSET = 0;
+    public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+    public static final int FLAGS_F_OFFSET = PREFIX_F_OFFSET + PREFIX_F_LENGTH;
+
+    public static final int CONTENT_LENGTH = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+
+    /*
+     * flags offset in bits
+     */
+    public static final int LPA_F_OFFSET = 7;
+    public static final int LPIU_F_OFFSET = 6;
+
+    public static RROIPAddressSubobject<IPv6Prefix> parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length != CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+       final IPv6Address address = new IPv6Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+       final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+       final BitSet flags = ByteArray.bytesToBitSet(Arrays.copyOfRange(soContentsBytes, FLAGS_F_OFFSET, FLAGS_F_OFFSET + FLAGS_F_LENGTH));
+
+       return new RROIPAddressSubobject<IPv6Prefix>(new IPv6Prefix(address, length), flags.get(LPA_F_OFFSET), flags.get(LPIU_F_OFFSET));
+    }
+
+    public static byte[] put(ReportedRouteSubobject objToSerialize) {
+       if (!(objToSerialize instanceof RROIPAddressSubobject))
+           throw new IllegalArgumentException("Unknown ReportedRouteSubobject instance. Passed " + objToSerialize.getClass()
+                   + ". Needed RROIPAddressSubobject.");
+
+       final RROIPAddressSubobject<?> specObj = (RROIPAddressSubobject<?>) objToSerialize;
+       final Prefix<?> prefix = specObj.getPrefix();
+
+       if (!(prefix instanceof IPv6Prefix))
+           throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv6Prefix.");
+
+       final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+
+       flags.set(LPA_F_OFFSET, specObj.isLocalProtectionAvailable());
+       flags.set(LPIU_F_OFFSET, specObj.isLocalProtectionInUse());
+
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+       ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+       retBytes[PREFIX_F_OFFSET] = ByteArray.intToBytes(prefix.getLength())[Integer.SIZE / Byte.SIZE - 1];
+       ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROLabelParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROLabelParser.java
new file mode 100644 (file)
index 0000000..a283ec9
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+
+public interface RROLabelParser {
+    RROLabelSubobject parse(byte[] cutBytes, boolean upStream) throws PCEPDeserializerException;
+
+    byte[] put(RROLabelSubobject objToSerialize);
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROLabelSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROLabelSubobjectParser.java
new file mode 100644 (file)
index 0000000..407c57b
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.Util.BiParsersMap;
+import org.opendaylight.protocol.pcep.subobject.RROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROType1LabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROLabelSubobjectParser {
+
+    public static final int RES_F_LENGTH = 1;
+
+    public static final int C_TYPE_F_LENGTH = 1;
+
+    public static final int RES_F_OFFSET = 0;
+
+    public static final int C_TYPE_F_OFFSET = RES_F_OFFSET + RES_F_LENGTH;
+
+    public static final int HEADER_LENGTH = C_TYPE_F_OFFSET + C_TYPE_F_LENGTH;
+
+    public static final int U_FLAG_OFFSET = 0;
+
+    private static class MapOfParsers extends BiParsersMap<Class<? extends RROLabelSubobject>, Integer, RROLabelParser> {
+       private final static MapOfParsers instance = new MapOfParsers();
+
+       private MapOfParsers() {
+           this.fillInMap();
+       }
+
+       private void fillInMap() {
+           this.put(RROType1LabelSubobject.class, 1, new RROType1LabelSubobjectParser());
+           this.put(RROGeneralizedLabelSubobject.class, 2, new RROGeneralizedLabelSubobjectParser());
+           this.put(RROWavebandSwitchingLabelSubobject.class, 3, new RROWavebandSwitchingLabelSubobjectParser());
+       }
+
+       public static MapOfParsers getInstance() {
+           return instance;
+       }
+    }
+
+    public static RROLabelSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length < HEADER_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + HEADER_LENGTH + ".");
+
+       final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(soContentsBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+       final int c_type = soContentsBytes[C_TYPE_F_OFFSET] & 0xFF;
+
+       final RROLabelParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+       if (parser == null) {
+           throw new PCEPDeserializerException("Unknown C-TYPE for ero label subobject. Passed: " + c_type);
+       }
+
+       return parser.parse(ByteArray.cutBytes(soContentsBytes, HEADER_LENGTH), reserved.get(U_FLAG_OFFSET));
+    }
+
+    public static byte[] put(RROLabelSubobject objToSerialize) {
+       final Integer c_type = MapOfParsers.getInstance().getKeyValueFromKey(objToSerialize.getClass());
+       final RROLabelParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+       if (c_type == null || parser == null)
+           throw new IllegalArgumentException("Unknown RROLabelSubobject instance. Passed " + objToSerialize.getClass());
+
+       final byte[] labelbytes = parser.put(objToSerialize);
+
+       final byte[] retBytes = new byte[labelbytes.length + HEADER_LENGTH];
+
+       System.arraycopy(labelbytes, 0, retBytes, HEADER_LENGTH, labelbytes.length);
+
+       final BitSet reserved = new BitSet();
+       reserved.set(U_FLAG_OFFSET, objToSerialize.isUpStream());
+       System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+       retBytes[C_TYPE_F_OFFSET] = (byte) c_type.intValue();
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROPathKeyWith128PCEIDSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROPathKeyWith128PCEIDSubobjectParser.java
new file mode 100644 (file)
index 0000000..edc0cbb
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROPathKeyWith128PCEIDSubobjectParser {
+
+    public static final int PK_F_LENGTH = 2;
+    public static final int PCE_ID_F_LENGTH = 16;
+
+    public static final int PK_F_OFFSET = 0;
+    public static final int PCE_ID_F_OFFSET = PK_F_OFFSET + PK_F_LENGTH;
+
+    public static final int CONTENT_LENGTH = PCE_ID_F_OFFSET + PCE_ID_F_LENGTH;
+
+    public static RROPathKeyWith128PCEIDSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length != CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+       final int pathKey = ByteArray.bytesToShort(Arrays.copyOfRange(soContentsBytes, PK_F_OFFSET, PCE_ID_F_OFFSET)) & 0xFFFF;
+
+       final byte[] pceId = Arrays.copyOfRange(soContentsBytes, PCE_ID_F_OFFSET, CONTENT_LENGTH);
+
+       return new RROPathKeyWith128PCEIDSubobject(pathKey, pceId);
+    }
+
+    public static byte[] put(RROPathKeyWith128PCEIDSubobject objToSerialize) {
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+       System.arraycopy(ByteArray.shortToBytes((short) objToSerialize.getPathKey()), 0, retBytes, PK_F_OFFSET, PK_F_LENGTH);
+
+       if (objToSerialize.getPceId().length != PCE_ID_F_LENGTH)
+           throw new IllegalArgumentException("Wrong length of pce id. Passed: " + objToSerialize.getPceId().length + ". Expected: =" + PCE_ID_F_LENGTH);
+       System.arraycopy(objToSerialize.getPceId(), 0, retBytes, PCE_ID_F_OFFSET, PCE_ID_F_LENGTH);
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROPathKeyWith32PCEIDSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROPathKeyWith32PCEIDSubobjectParser.java
new file mode 100644 (file)
index 0000000..2668d79
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROPathKeyWith32PCEIDSubobjectParser {
+
+    public static final int PK_F_LENGTH = 2;
+    public static final int PCE_ID_F_LENGTH = 4;
+
+    public static final int PK_F_OFFSET = 0;
+    public static final int PCE_ID_F_OFFSET = PK_F_OFFSET + PK_F_LENGTH;
+
+    public static final int CONTENT_LENGTH = PCE_ID_F_OFFSET + PCE_ID_F_LENGTH;
+
+    public static RROPathKeyWith32PCEIDSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length != CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: =" + CONTENT_LENGTH + ".");
+
+       final int pathKey = ByteArray.bytesToShort(Arrays.copyOfRange(soContentsBytes, PK_F_OFFSET, PCE_ID_F_OFFSET)) & 0xFFFF;
+
+       final byte[] pceId = Arrays.copyOfRange(soContentsBytes, PCE_ID_F_OFFSET, CONTENT_LENGTH);
+
+       return new RROPathKeyWith32PCEIDSubobject(pathKey, pceId);
+    }
+
+    public static byte[] put(RROPathKeyWith32PCEIDSubobject objToSerialize) {
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+       System.arraycopy(ByteArray.shortToBytes((short) objToSerialize.getPathKey()), 0, retBytes, PK_F_OFFSET, PK_F_LENGTH);
+
+       if (objToSerialize.getPceId().length != PCE_ID_F_LENGTH)
+           throw new IllegalArgumentException("Wrong length of pce id. Passed: " + objToSerialize.getPceId().length + ". Expected: =" + PCE_ID_F_LENGTH);
+       System.arraycopy(objToSerialize.getPceId(), 0, retBytes, PCE_ID_F_OFFSET, PCE_ID_F_LENGTH);
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionParser.java
new file mode 100644 (file)
index 0000000..643a929
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
+
+public interface RROProtectionParser {
+
+    RROProtectionSubobject parse(byte[] cutBytes) throws PCEPDeserializerException;
+
+    byte[] put(RROProtectionSubobject objToSerialize);
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionSubobjectParser.java
new file mode 100644 (file)
index 0000000..7de1a93
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.Util.BiParsersMap;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType1Subobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType2Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROProtectionSubobjectParser {
+
+    public static final int RES_F_LENGTH = 1;
+
+    public static final int C_TYPE_F_LENGTH = 1;
+
+    public static final int RES_F_OFFSET = 0;
+
+    public static final int C_TYPE_F_OFFSET = RES_F_OFFSET + RES_F_LENGTH;
+
+    public static final int HEADER_LENGTH = C_TYPE_F_OFFSET + C_TYPE_F_LENGTH;
+
+    public static final int U_FLAG_OFFSET = 0;
+
+    private static class MapOfParsers extends BiParsersMap<Class<? extends RROProtectionSubobject>, Integer, RROProtectionParser> {
+       private final static MapOfParsers instance = new MapOfParsers();
+
+       private MapOfParsers() {
+           this.fillInMap();
+       }
+
+       private void fillInMap() {
+           this.put(RROProtectionType1Subobject.class, 1, new RROProtectionType1SubobjectParser());
+           this.put(RROProtectionType2Subobject.class, 2, new RROProtectionType2SubobjectParser());
+       }
+
+       public static MapOfParsers getInstance() {
+           return instance;
+       }
+    }
+
+    public static RROProtectionSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+       if (soContentsBytes == null || soContentsBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (soContentsBytes.length < HEADER_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + HEADER_LENGTH + ".");
+
+       final int c_type = soContentsBytes[C_TYPE_F_OFFSET] & 0xFF;
+
+       final RROProtectionParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+       if (parser == null) {
+           throw new PCEPDeserializerException("Unknown C-TYPE for ero protection subobject. Passed: " + c_type);
+       }
+
+       return parser.parse(ByteArray.cutBytes(soContentsBytes, HEADER_LENGTH));
+    }
+
+    public static byte[] put(RROProtectionSubobject objToSerialize) {
+       final Integer c_type = MapOfParsers.getInstance().getKeyValueFromKey(objToSerialize.getClass());
+       final RROProtectionParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+       if (c_type == null || parser == null)
+           throw new IllegalArgumentException("Unknown EROProtectionSubobject instance. Passed " + objToSerialize.getClass());
+
+       final byte[] protBytes = parser.put(objToSerialize);
+
+       final byte[] retBytes = new byte[protBytes.length + HEADER_LENGTH];
+
+       System.arraycopy(protBytes, 0, retBytes, HEADER_LENGTH, protBytes.length);
+
+       retBytes[C_TYPE_F_OFFSET] = (byte) c_type.intValue();
+
+       return retBytes;
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionType1SubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionType1SubobjectParser.java
new file mode 100644 (file)
index 0000000..f7629ba
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType1Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROProtectionType1SubobjectParser implements RROProtectionParser {
+
+    public static final int RES_F_LENGTH = 4;
+
+    public static final int RES_F_OFFSET = 0;
+
+    public static final int CONTENT_LENGTH = RES_F_OFFSET + RES_F_LENGTH;
+
+    /*
+     * offsets of flags inside reserved field
+     */
+    public static final int S_FLAG_OFFSET = 0;
+
+    @Override
+    public RROProtectionSubobject parse(byte[] cutBytes) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (cutBytes.length < CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+       final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(cutBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+       final byte linkFlags = (byte) (cutBytes[3] & 0x3F);
+
+       return new RROProtectionType1Subobject(reserved.get(S_FLAG_OFFSET), linkFlags);
+    }
+
+    @Override
+    public byte[] put(RROProtectionSubobject objToSerialize) {
+       if (!(objToSerialize instanceof RROProtectionType1Subobject))
+           throw new IllegalArgumentException("Unknown RROProtectionSubobject instance. Passed " + objToSerialize.getClass()
+                   + ". Needed RROProtectionType1Subobject.");
+
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+       final BitSet reserved = new BitSet();
+       reserved.set(S_FLAG_OFFSET, ((RROProtectionType1Subobject) objToSerialize).isSecondary());
+       System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+       retBytes[3] |= ((RROProtectionType1Subobject) objToSerialize).getLinkFlags() & 0x3F;
+
+       return retBytes;
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionType2SubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROProtectionType2SubobjectParser.java
new file mode 100644 (file)
index 0000000..8aeaf68
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType2Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROProtectionType2SubobjectParser implements RROProtectionParser {
+
+    public static final int RES_F_LENGTH = 8;
+
+    public static final int RES_F_OFFSET = 0;
+
+    public static final int CONTENT_LENGTH = RES_F_OFFSET + RES_F_LENGTH;
+
+    /*
+     * offsets of flags inside reserved field
+     */
+    public static final int S_FLAG_OFFSET = 0;
+    public static final int P_FLAG_OFFSET = 1;
+    public static final int N_FLAG_OFFSET = 2;
+    public static final int O_FLAG_OFFSET = 3;
+
+    public static final int I_FLAG_OFFSET = 32;
+    public static final int R_FLAG_OFFSET = 33;
+
+    @Override
+    public RROProtectionSubobject parse(byte[] cutBytes) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (cutBytes.length < CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+       final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(cutBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+       final byte linkFlags = (byte) (cutBytes[3] & 0x3F);
+       final byte lspFlags = (byte) (cutBytes[1] & 0x3F);
+       final byte segFlags = (byte) (cutBytes[5] & 0x3F);
+
+       return new RROProtectionType2Subobject(reserved.get(S_FLAG_OFFSET), reserved.get(P_FLAG_OFFSET), reserved.get(N_FLAG_OFFSET),
+               reserved.get(N_FLAG_OFFSET), lspFlags, linkFlags, reserved.get(I_FLAG_OFFSET), reserved.get(R_FLAG_OFFSET), segFlags);
+    }
+
+    @Override
+    public byte[] put(RROProtectionSubobject objToSerialize) {
+       if (!(objToSerialize instanceof RROProtectionType2Subobject))
+           throw new IllegalArgumentException("Unknown RROProtectionSubobject instance. Passed " + objToSerialize.getClass()
+                   + ". Needed RROProtectionType2Subobject.");
+
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+       final BitSet reserved = new BitSet();
+       reserved.set(S_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isSecondaryLsp());
+       reserved.set(P_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isProtectionLsp());
+       reserved.set(N_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isNotification());
+       reserved.set(O_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isOperational());
+       reserved.set(I_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isInPlace());
+       reserved.set(R_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isRequired());
+       System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+       retBytes[3] |= ((RROProtectionType2Subobject) objToSerialize).getLinkFlags() & 0x3F;
+       retBytes[1] |= ((RROProtectionType2Subobject) objToSerialize).getLspFlags() & 0x3F;
+       retBytes[5] |= ((RROProtectionType2Subobject) objToSerialize).getSegFlags() & 0x3F;
+
+       return retBytes;
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROType1LabelSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROType1LabelSubobjectParser.java
new file mode 100644 (file)
index 0000000..ed81e66
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROType1LabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+public class RROType1LabelSubobjectParser implements RROLabelParser {
+
+    public static final int LABEL_LENGTH = 4;
+
+    @Override
+    public RROLabelSubobject parse(byte[] cutBytes, boolean upStream) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+       if (cutBytes.length != LABEL_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: " + LABEL_LENGTH + ".");
+
+       return new RROType1LabelSubobject(UnsignedInts.toLong(ByteArray.bytesToInt(cutBytes)), upStream);
+    }
+
+    @Override
+    public byte[] put(RROLabelSubobject objToSerialize) {
+       if (!(objToSerialize instanceof RROType1LabelSubobject))
+           throw new IllegalArgumentException("Unknown RROLabelSubobject instance. Passed " + objToSerialize.getClass() + ". Needed RROType1LabelSubobject.");
+
+       return ByteArray.intToBytes((int) ((RROType1LabelSubobject) objToSerialize).getLabel());
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROUnnumberedInterfaceSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROUnnumberedInterfaceSubobjectParser.java
new file mode 100644 (file)
index 0000000..edcea4e
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for
+ * {@link org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject
+ * RROUnnumberedInterfaceSubobject}
+ */
+public class RROUnnumberedInterfaceSubobjectParser {
+       public static final int ROUTER_ID_NUMBER_LENGTH = 4;
+       public static final int INTERFACE_ID_NUMBER_LENGTH = 4;
+
+       public static final int ROUTER_ID_NUMBER_OFFSET = 2; // added reserved field of size 2
+       public static final int INTERFACE_ID_NUMBER_OFFSET = ROUTER_ID_NUMBER_OFFSET + ROUTER_ID_NUMBER_LENGTH;
+
+       public static final int CONTENT_LENGTH = INTERFACE_ID_NUMBER_OFFSET + INTERFACE_ID_NUMBER_LENGTH;
+
+       public static RROUnnumberedInterfaceSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               return new RROUnnumberedInterfaceSubobject(new IPv4Address(
+                               ByteArray.subByte(soContentsBytes, ROUTER_ID_NUMBER_OFFSET, ROUTER_ID_NUMBER_LENGTH)), new UnnumberedInterfaceIdentifier(
+                               UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(soContentsBytes, INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH)))));
+       }
+
+       public static byte[] put(ReportedRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof RROUnnumberedInterfaceSubobject))
+                       throw new IllegalArgumentException("Unknown ReportedRouteSubobject instance. Passed " + objToSerialize.getClass()
+                                       + ". Needed RROUnnumberedInterfaceSubobject.");
+
+               byte[] retBytes;
+               retBytes = new byte[CONTENT_LENGTH];
+               final RROUnnumberedInterfaceSubobject specObj = (RROUnnumberedInterfaceSubobject) objToSerialize;
+
+               ByteArray.copyWhole(specObj.getRouterID().getAddress(), retBytes, ROUTER_ID_NUMBER_OFFSET);
+               System.arraycopy(ByteArray.longToBytes(specObj.getInterfaceID().getInterfaceId()), Long.SIZE / Byte.SIZE - INTERFACE_ID_NUMBER_LENGTH, retBytes,
+                               INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH);
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROWavebandSwitchingLabelSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/RROWavebandSwitchingLabelSubobjectParser.java
new file mode 100644 (file)
index 0000000..b002970
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+public class RROWavebandSwitchingLabelSubobjectParser implements RROLabelParser {
+
+    public static int WAVEB_F_LENGTH = 4;
+    public static int START_F_LENGTH = 4;
+    public static int END_F_LENGTH = 4;
+
+    public static int WAVEB_F_OFFSET = 0;
+    public static int START_F_OFFSET = WAVEB_F_OFFSET + WAVEB_F_LENGTH;
+    public static int END_F_OFFSET = START_F_OFFSET + START_F_LENGTH;
+
+    public static int CONTENT_LENGTH = END_F_OFFSET + END_F_LENGTH;
+
+    @Override
+    public RROLabelSubobject parse(byte[] cutBytes, boolean upStream) throws PCEPDeserializerException {
+       if (cutBytes == null || cutBytes.length == 0)
+           throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+       if (cutBytes.length != CONTENT_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+       return new RROWavebandSwitchingLabelSubobject(UnsignedInts.toLong(ByteArray.bytesToInt(Arrays.copyOfRange(cutBytes, WAVEB_F_OFFSET, START_F_OFFSET))),
+               UnsignedInts.toLong(ByteArray.bytesToInt(Arrays.copyOfRange(cutBytes, START_F_OFFSET, END_F_OFFSET))), UnsignedInts.toLong(ByteArray
+                       .bytesToInt(Arrays.copyOfRange(cutBytes, END_F_OFFSET, CONTENT_LENGTH))), upStream);
+    }
+
+    @Override
+    public byte[] put(RROLabelSubobject objToSerialize) {
+       if (!(objToSerialize instanceof RROWavebandSwitchingLabelSubobject))
+           throw new IllegalArgumentException("Unknown RROLabelSubobject instance. Passed " + objToSerialize.getClass()
+                   + ". Needed RROWavebandSwitchingLabelSubobject.");
+       final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+       final RROWavebandSwitchingLabelSubobject obj = (RROWavebandSwitchingLabelSubobject) objToSerialize;
+
+       System.arraycopy(ByteArray.intToBytes((int) obj.getWavebandId()), 0, retBytes, WAVEB_F_OFFSET, WAVEB_F_LENGTH);
+       System.arraycopy(ByteArray.intToBytes((int) obj.getStartLabel()), 0, retBytes, START_F_OFFSET, START_F_LENGTH);
+       System.arraycopy(ByteArray.intToBytes((int) obj.getEndLabel()), 0, retBytes, END_F_OFFSET, END_F_LENGTH);
+
+       return retBytes;
+    }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROAsNumberSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROAsNumberSubobjectParser.java
new file mode 100644 (file)
index 0000000..e9cc60a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject
+ * XROAsNumberSubobject}
+ */
+
+public class XROAsNumberSubobjectParser {
+       public static final int AS_NUMBER_LENGTH = 2;
+
+       public static final int AS_NUMBER_OFFSET = 0;
+
+       public static final int CONTENT_LENGTH = AS_NUMBER_LENGTH + AS_NUMBER_OFFSET;
+
+       public static XROAsNumberSubobject parse(byte[] soContentsBytes, boolean mandatory) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               return new XROAsNumberSubobject(new ASNumber((ByteArray.bytesToShort(soContentsBytes) & 0xFFFF)), mandatory);
+       }
+
+       public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof XROAsNumberSubobject))
+                       throw new IllegalArgumentException("Unknown PCEPXROSubobject instance. Passed " + objToSerialize.getClass() + ". Needed XROAsNumberSubobject.");
+
+               final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+               System.arraycopy(ByteArray.longToBytes(((XROAsNumberSubobject) objToSerialize).getASNumber().getAsn()), Long.SIZE / Byte.SIZE - AS_NUMBER_LENGTH,
+                               retBytes, AS_NUMBER_OFFSET, AS_NUMBER_LENGTH);
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROIPv4PrefixSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROIPv4PrefixSubobjectParser.java
new file mode 100644 (file)
index 0000000..199bf74
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject
+ * XROIPPrefixSubobject<IPv4Prefix>}
+ */
+public class XROIPv4PrefixSubobjectParser {
+       public static final int IP_F_LENGTH = 4;
+       public static final int PREFIX_F_LENGTH = 1;
+       public static final int ATTRIBUTE_LENGTH = 1;
+
+       public static final int IP_F_OFFSET = 0;
+       public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+       public static final int ATTRIBUTE_OFFSET = PREFIX_F_OFFSET + PREFIX_F_LENGTH;
+
+       public static final int CONTENT_LENGTH = ATTRIBUTE_OFFSET + ATTRIBUTE_LENGTH;
+
+       public static XROIPPrefixSubobject<IPv4Prefix> parse(byte[] soContentsBytes, boolean mandatory) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               final IPv4Address address = new IPv4Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+               final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+               return new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(address, length), mandatory, XROSubobjectAttributeMapping.getInstance()
+                               .getFromAttributeIdentifier((short) (soContentsBytes[ATTRIBUTE_OFFSET] & 0xFF)));
+       }
+
+       public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof XROIPPrefixSubobject))
+                       throw new IllegalArgumentException("Unknown PCEPXROSubobject instance. Passed " + objToSerialize.getClass() + ". Needed XROIPPrefixSubobject.");
+
+               final XROIPPrefixSubobject<?> specObj = (XROIPPrefixSubobject<?>) objToSerialize;
+               final Prefix<?> prefix = specObj.getPrefix();
+
+               if (!(prefix instanceof IPv4Prefix))
+                       throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv4Prefix.");
+
+               final byte[] retBytes = new byte[CONTENT_LENGTH];
+               ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+               retBytes[PREFIX_F_OFFSET] = (byte) prefix.getLength();
+               retBytes[ATTRIBUTE_OFFSET] = (byte) XROSubobjectAttributeMapping.getInstance().getFromAttributeEnum(specObj.getAttribute());
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROIPv6PrefixSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROIPv6PrefixSubobjectParser.java
new file mode 100644 (file)
index 0000000..21b5291
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject
+ * XROIPPrefixSubobject<IPv6Prefix>}
+ */
+public class XROIPv6PrefixSubobjectParser {
+       public static final int IP_F_LENGTH = 16;
+       public static final int PREFIX_F_LENGTH = 1;
+       public static final int ATTRIBUTE_LENGTH = 1;
+
+       public static final int IP_F_OFFSET = 0;
+       public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+       public static final int ATTRIBUTE_OFFSET = PREFIX_F_OFFSET + PREFIX_F_LENGTH;
+
+       public static final int CONTENT_LENGTH = ATTRIBUTE_OFFSET + ATTRIBUTE_LENGTH;
+
+       public static XROIPPrefixSubobject<IPv6Prefix> parse(byte[] soContentsBytes, boolean mandatory) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               final IPv6Address address = new IPv6Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+               final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+               return new XROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(address, length), mandatory, XROSubobjectAttributeMapping.getInstance()
+                               .getFromAttributeIdentifier((short) (soContentsBytes[ATTRIBUTE_OFFSET] & 0xFF)));
+       }
+
+       public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof XROIPPrefixSubobject))
+                       throw new IllegalArgumentException("Unknown PCEPXROSubobject instance. Passed " + objToSerialize.getClass() + ". Needed XROIPPrefixSubobject.");
+
+               final XROIPPrefixSubobject<?> specObj = (XROIPPrefixSubobject<?>) objToSerialize;
+               final Prefix<?> prefix = specObj.getPrefix();
+
+               if (!(prefix instanceof IPv6Prefix))
+                       throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv6Prefix.");
+
+               final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+               ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+               retBytes[PREFIX_F_OFFSET] = (byte) prefix.getLength();
+               retBytes[ATTRIBUTE_OFFSET] = (byte) XROSubobjectAttributeMapping.getInstance().getFromAttributeEnum(specObj.getAttribute());
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROSRLGSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROSRLGSubobjectParser.java
new file mode 100644 (file)
index 0000000..e1a041c
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject. XROSRLGSubobject
+ * XROSRLGSubobject}
+ */
+public class XROSRLGSubobjectParser {
+       public static final int SRLG_ID_NUMBER_LENGTH = 4;
+       public static final int ATTRIBUTE_LENGTH = 1;
+
+       public static final int SRLG_ID_NUMBER_OFFSET = 0;
+       public static final int ATTRIBUTE_OFFSET = SRLG_ID_NUMBER_OFFSET + SRLG_ID_NUMBER_LENGTH + 1; // added reserved field of size 1
+
+       public static final int CONTENT_LENGTH = ATTRIBUTE_OFFSET + ATTRIBUTE_LENGTH;
+
+       public static XROSRLGSubobject parse(byte[] soContentsBytes, boolean mandatory) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               return new XROSRLGSubobject(new SharedRiskLinkGroup(UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(soContentsBytes, SRLG_ID_NUMBER_OFFSET,
+                               SRLG_ID_NUMBER_LENGTH)))), mandatory);
+       }
+
+       public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof XROSRLGSubobject))
+                       throw new IllegalArgumentException("Unknown PCEPXROSubobject instance. Passed " + objToSerialize.getClass() + ". Needed XROSRLGSubobject.");
+
+               byte[] retBytes;
+               retBytes = new byte[CONTENT_LENGTH];
+               final XROSRLGSubobject specObj = (XROSRLGSubobject) objToSerialize;
+
+               ByteArray.copyWhole(ByteArray.intToBytes((int) specObj.getSrlgId().getValue()), retBytes, SRLG_ID_NUMBER_OFFSET);
+               retBytes[ATTRIBUTE_OFFSET] = (byte) XROSubobjectAttributeMapping.getInstance().getFromAttributeEnum(specObj.getAttribute());
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROSubobjectAttributeMapping.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROSubobjectAttributeMapping.java
new file mode 100644 (file)
index 0000000..0e993ef
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.opendaylight.protocol.pcep.subobject.XROSubobjectAttribute;
+
+/**
+ * Bidirectional mapping for XROSubobjectAttribute and appropriate identifier.
+ */
+public class XROSubobjectAttributeMapping {
+       private static final XROSubobjectAttributeMapping instance = new XROSubobjectAttributeMapping();
+
+       private final Map<XROSubobjectAttribute, Integer> ofCodesMap = new EnumMap<XROSubobjectAttribute, Integer>(XROSubobjectAttribute.class);
+       private final Map<Integer, XROSubobjectAttribute> ofCodeIdsMap = new HashMap<Integer, XROSubobjectAttribute>();
+
+       private XROSubobjectAttributeMapping() {
+               this.fillIn();
+       }
+
+       private void fillIn() {
+               this.fillIn(0, XROSubobjectAttribute.INTERFACE);
+               this.fillIn(1, XROSubobjectAttribute.NODE);
+               this.fillIn(2, XROSubobjectAttribute.SRLG);
+       }
+
+       private void fillIn(int identifier, XROSubobjectAttribute ofCode) {
+               this.ofCodesMap.put(ofCode, identifier);
+               this.ofCodeIdsMap.put(identifier, ofCode);
+       }
+
+       public int getFromAttributeEnum(XROSubobjectAttribute ofCode) {
+               final Integer ofci = this.ofCodesMap.get(ofCode);
+               if (ofci == null)
+                       throw new NoSuchElementException("Unknown XROSubobjectAttribute type: " + ofCode);
+               return ofci;
+       }
+
+       public XROSubobjectAttribute getFromAttributeIdentifier(int identifier) {
+               final XROSubobjectAttribute ofc = this.ofCodeIdsMap.get(identifier);
+               if (ofc == null)
+                       throw new NoSuchElementException("Unknown XROSubobjectAttribute identifier.");
+               return ofc;
+       }
+
+       public static XROSubobjectAttributeMapping getInstance() {
+               return instance;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROUnnumberedInterfaceSubobjectParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/subobject/XROUnnumberedInterfaceSubobjectParser.java
new file mode 100644 (file)
index 0000000..9b7f400
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for
+ * {@link org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject
+ * XROUnnumberedInterfaceSubobject}
+ */
+public class XROUnnumberedInterfaceSubobjectParser {
+       public static final int ATTRIBUTE_LENGTH = 1;
+       public static final int ROUTER_ID_NUMBER_LENGTH = 4;
+       public static final int INTERFACE_ID_NUMBER_LENGTH = 4;
+
+       public static final int ATTRIBUTE_OFFSET = 1;// added reserved field of size 1
+       public static final int ROUTER_ID_NUMBER_OFFSET = ATTRIBUTE_OFFSET + ATTRIBUTE_LENGTH;
+       public static final int INTERFACE_ID_NUMBER_OFFSET = ROUTER_ID_NUMBER_OFFSET + ROUTER_ID_NUMBER_LENGTH;
+
+       public static final int CONTENT_LENGTH = INTERFACE_ID_NUMBER_OFFSET + INTERFACE_ID_NUMBER_LENGTH;
+
+       public static XROUnnumberedInterfaceSubobject parse(byte[] soContentsBytes, boolean mandatory) throws PCEPDeserializerException {
+               if (soContentsBytes == null || soContentsBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+               if (soContentsBytes.length != CONTENT_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+               return new XROUnnumberedInterfaceSubobject(new IPv4Address(
+                               ByteArray.subByte(soContentsBytes, ROUTER_ID_NUMBER_OFFSET, ROUTER_ID_NUMBER_LENGTH)), new UnnumberedInterfaceIdentifier(
+                               UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(soContentsBytes, INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH)))),
+                               mandatory, XROSubobjectAttributeMapping.getInstance().getFromAttributeIdentifier((short) (soContentsBytes[ATTRIBUTE_OFFSET] & 0xFF)));
+       }
+
+       public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+               if (!(objToSerialize instanceof XROUnnumberedInterfaceSubobject))
+                       throw new IllegalArgumentException("Unknown PCEPXROSubobject instance. Passed " + objToSerialize.getClass()
+                                       + ". Needed XROUnnumberedInterfaceSubobject.");
+
+               byte[] retBytes;
+               retBytes = new byte[CONTENT_LENGTH];
+               final XROUnnumberedInterfaceSubobject specObj = (XROUnnumberedInterfaceSubobject) objToSerialize;
+
+               retBytes[ATTRIBUTE_OFFSET] = (byte) XROSubobjectAttributeMapping.getInstance().getFromAttributeEnum(specObj.getAttribute());
+               ByteArray.copyWhole(specObj.getRouterID().getAddress(), retBytes, ROUTER_ID_NUMBER_OFFSET);
+               System.arraycopy(ByteArray.longToBytes(specObj.getInterfaceID().getInterfaceId()), Long.SIZE / Byte.SIZE - INTERFACE_ID_NUMBER_LENGTH, retBytes,
+                               INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH);
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/LSPIdentifierIPv4TlvParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/LSPIdentifierIPv4TlvParser.java
new file mode 100644 (file)
index 0000000..995e952
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.tlv;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.IPv4ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+import org.opendaylight.protocol.pcep.tlv.IPv4LSPIdentifiersTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.LSPIdentifiersTlv LSPIdentifiersTlv}
+ * parameterized as IPv4Address
+ */
+public class LSPIdentifierIPv4TlvParser {
+
+       private static final int IP_F_LENGTH = 4;
+       private static final int LSP_ID_F_LENGTH = 2;
+       private static final int TUNNEL_ID_F_LENGTH = 2;
+       private static final int EX_TUNNEL_ID_F_LENGTH = 4;
+
+       private static final int IP_F_OFFSET = 0;
+       private static final int LSP_ID_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+       private static final int TUNNLE_ID_F_OFFSET = LSP_ID_F_OFFSET + LSP_ID_F_LENGTH;
+       private static final int EX_TUNNEL_ID_F_OFFSET = TUNNLE_ID_F_OFFSET + TUNNEL_ID_F_LENGTH;
+
+       private static final int SIZE = EX_TUNNEL_ID_F_OFFSET + EX_TUNNEL_ID_F_LENGTH;
+
+       public static IPv4LSPIdentifiersTlv parse(byte[] valueBytes) throws PCEPDeserializerException {
+               if (valueBytes == null || valueBytes.length == 0)
+                       throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+               if (valueBytes.length != SIZE)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: " + SIZE + ".");
+
+               return new IPv4LSPIdentifiersTlv(new IPv4Address(
+                               ByteArray.subByte(valueBytes, IP_F_OFFSET, IP_F_LENGTH)), new LSPIdentifier(ByteArray.subByte(valueBytes, LSP_ID_F_OFFSET, LSP_ID_F_LENGTH)),
+                               new TunnelIdentifier(ByteArray.subByte(valueBytes, TUNNLE_ID_F_OFFSET, TUNNEL_ID_F_LENGTH)),
+                               new IPv4ExtendedTunnelIdentifier(new IPv4Address(ByteArray.subByte(valueBytes, EX_TUNNEL_ID_F_OFFSET, EX_TUNNEL_ID_F_LENGTH))));
+       }
+
+       public static byte[] put(IPv4LSPIdentifiersTlv objToSerialize) {
+               if (objToSerialize == null)
+                       throw new IllegalArgumentException("IPv4LSPIdentifiersTlv is mandatory.");
+
+               final byte[] retBytes = new byte[SIZE];
+
+               ByteArray.copyWhole(objToSerialize.getSenderAddress().getAddress(), retBytes, IP_F_OFFSET);
+               ByteArray.copyWhole(objToSerialize.getLspID().getLspId(), retBytes, LSP_ID_F_OFFSET);
+               ByteArray.copyWhole(objToSerialize.getTunnelID().getBytes(), retBytes, TUNNLE_ID_F_OFFSET);
+               ByteArray.copyWhole(objToSerialize.getExtendedTunnelID().getIdentifier().getAddress(), retBytes, EX_TUNNEL_ID_F_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/LSPIdentifierIPv6TlvParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/LSPIdentifierIPv6TlvParser.java
new file mode 100644 (file)
index 0000000..0133e85
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.tlv;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.IPv6ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+import org.opendaylight.protocol.pcep.tlv.IPv6LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPIdentifiersTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.LSPIdentifiersTlv LSPIdentifiersTlv}
+ * parameterized as IPv6Address
+ */
+public class LSPIdentifierIPv6TlvParser {
+
+       private static final int IP_F_LENGTH = 16;
+       private static final int LSP_ID_F_LENGTH = 2;
+       private static final int TUNNEL_ID_F_LENGTH = 2;
+       private static final int EX_TUNNEL_ID_F_LENGTH = 16;
+
+       private static final int IP_F_OFFSET = 0;
+       private static final int LSP_ID_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+       private static final int TUNNLE_ID_F_OFFSET = LSP_ID_F_OFFSET + LSP_ID_F_LENGTH;
+       private static final int EX_TUNNEL_ID_F_OFFSET = TUNNLE_ID_F_OFFSET + TUNNEL_ID_F_LENGTH;
+
+       private static final int SIZE = EX_TUNNEL_ID_F_OFFSET + EX_TUNNEL_ID_F_LENGTH;
+
+       public static LSPIdentifiersTlv<IPv6Address> parse(byte[] valueBytes) throws PCEPDeserializerException {
+               if (valueBytes == null || valueBytes.length == 0)
+                       throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+               if (valueBytes.length != SIZE)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: " + SIZE + ".");
+
+               return new IPv6LSPIdentifiersTlv(new IPv6Address(
+                               ByteArray.subByte(valueBytes, IP_F_OFFSET, IP_F_LENGTH)), new LSPIdentifier(ByteArray.subByte(valueBytes, LSP_ID_F_OFFSET, LSP_ID_F_LENGTH)),
+                               new TunnelIdentifier(ByteArray.subByte(valueBytes, TUNNLE_ID_F_OFFSET, TUNNEL_ID_F_LENGTH)),
+                               new IPv6ExtendedTunnelIdentifier(new IPv6Address(ByteArray.subByte(valueBytes, EX_TUNNEL_ID_F_OFFSET, EX_TUNNEL_ID_F_LENGTH))));
+       }
+
+       public static byte[] put(IPv6LSPIdentifiersTlv objToSerialize) {
+               if (objToSerialize == null)
+                       throw new IllegalArgumentException("IPv6LSPIdentifiersTlv is mandatory.");
+
+               final byte[] retBytes = new byte[SIZE];
+
+               ByteArray.copyWhole(objToSerialize.getSenderAddress().getAddress(), retBytes, IP_F_OFFSET);
+               ByteArray.copyWhole(objToSerialize.getLspID().getLspId(), retBytes, LSP_ID_F_OFFSET);
+               ByteArray.copyWhole(objToSerialize.getTunnelID().getBytes(), retBytes, TUNNLE_ID_F_OFFSET);
+               ByteArray.copyWhole(objToSerialize.getExtendedTunnelID().getIdentifier().getAddress(), retBytes, EX_TUNNEL_ID_F_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/NoPathVectorTlvParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/NoPathVectorTlvParser.java
new file mode 100644 (file)
index 0000000..1f651de
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.tlv;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv NoPathVectorTlv}
+ */
+public class NoPathVectorTlvParser {
+
+       public static final int FLAGS_F_LENGTH = 4;
+
+       /*
+        * flags offsets inside flags field in bits
+        */
+       public static final int PCE_UNAVAILABLE = 31;
+       public static final int UNKNOWN_DEST = 30;
+       public static final int UNKNOWN_SRC = 29;
+
+       /*
+        * flags offsets of flags added by GCO extension
+        */
+       public static final int NO_GCO_SOLUTION = 25;
+       public static final int NO_GCO_MIGRATION_PATH = 26;
+
+       /*
+        * flags offsets of flags added by RFC 6006
+        */
+       public static final int REACHABLITY_PROBLEM = 24;
+
+       public static NoPathVectorTlv parse(byte[] valueBytes) throws PCEPDeserializerException {
+               if (valueBytes == null || valueBytes.length == 0)
+                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+               if (valueBytes.length != FLAGS_F_LENGTH)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: >=" + FLAGS_F_LENGTH + ".");
+
+               final BitSet flags = ByteArray.bytesToBitSet(valueBytes);
+               return new NoPathVectorTlv(flags.get(PCE_UNAVAILABLE), flags.get(UNKNOWN_DEST), flags.get(UNKNOWN_SRC), flags.get(NO_GCO_SOLUTION),
+                               flags.get(NO_GCO_MIGRATION_PATH), flags.get(REACHABLITY_PROBLEM));
+       }
+
+       public static byte[] put(NoPathVectorTlv obj) {
+               if (obj == null)
+                       throw new IllegalArgumentException("NoPathVectorTlv is mandatory.");
+
+               final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+
+               flags.set(PCE_UNAVAILABLE, obj.isPceUnavailable());
+               flags.set(UNKNOWN_DEST, obj.isUnknownDest());
+               flags.set(UNKNOWN_SRC, obj.isUnknownSrc());
+               flags.set(NO_GCO_SOLUTION, obj.isNoGCOSolution());
+               flags.set(NO_GCO_MIGRATION_PATH, obj.isNoGCOMigrationPath());
+               flags.set(REACHABLITY_PROBLEM, obj.isReachablityProblem());
+
+               return ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH);
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/OFListTlvParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/OFListTlvParser.java
new file mode 100644 (file)
index 0000000..1c98f17
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.tlv;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.impl.PCEPOFCodesMapping;
+import org.opendaylight.protocol.pcep.tlv.OFListTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.OFListTlv OFListTlv}
+ */
+public class OFListTlvParser {
+
+       private static final int OF_CODE_ELEMENT_LENGTH = 2;
+
+       public static OFListTlv parse(byte[] valueBytes) throws PCEPDeserializerException {
+               if (valueBytes == null || valueBytes.length == 0)
+                       throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+               if (valueBytes.length % OF_CODE_ELEMENT_LENGTH != 0)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + ".");
+
+               final List<PCEPOFCodes> ofCodes = new ArrayList<PCEPOFCodes>();
+               for (int i = 0; i < valueBytes.length; i += OF_CODE_ELEMENT_LENGTH) {
+                       try {
+                               ofCodes.add(PCEPOFCodesMapping.getInstance().getFromCodeIdentifier(
+                                               ByteArray.bytesToShort(Arrays.copyOfRange(valueBytes, i, i + OF_CODE_ELEMENT_LENGTH)) & 0xFFFF));
+                       } catch (final NoSuchElementException nsee) {
+                               throw new PCEPDeserializerException(nsee, "Unknown OF Code inside OF Code list Tlv.");
+                       }
+               }
+
+               return new OFListTlv(ofCodes);
+       }
+
+       public static byte[] put(OFListTlv objToSerialize) {
+               if (objToSerialize == null)
+                       throw new IllegalArgumentException("OFListTlv is mandatory.");
+
+               final List<PCEPOFCodes> ofCodes = objToSerialize.getOfCodes();
+               final byte[] retBytes = new byte[ofCodes.size() * OF_CODE_ELEMENT_LENGTH];
+
+               final int size = ofCodes.size();
+               for (int i = 0; i < size; i++) {
+                       ByteArray.copyWhole(ByteArray.shortToBytes((short) PCEPOFCodesMapping.getInstance().getFromOFCodesEnum(ofCodes.get(i))), retBytes, i
+                                       * OF_CODE_ELEMENT_LENGTH);
+               }
+
+               return retBytes;
+       }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/PCEStatefulCapabilityTlvParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/PCEStatefulCapabilityTlvParser.java
new file mode 100644 (file)
index 0000000..c19febe
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.tlv;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv
+ * PCEStatefulCapabilityTlv}
+ * 
+ * @see <a
+ *      href="http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt#section-4.1">
+ *      Stateful PCE Capability TLV</a>
+ */
+public final class PCEStatefulCapabilityTlvParser {
+    /*
+     * Flags field length in Bytes
+     */
+    public static final int FLAGS_F_LENGTH = 4;
+
+    /*
+     * Offsets inside flags field in bits;
+     */
+    public static final int I_FLAG_OFFSET = 29;
+    public static final int S_FLAG_OFFSET = 30;
+    public static final int U_FLAG_OFFSET = 31;
+
+    public static PCEStatefulCapabilityTlv deserializeValueField(byte[] valueBytes) throws PCEPDeserializerException {
+       if (valueBytes == null || valueBytes.length == 0)
+           throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+       if (valueBytes.length < FLAGS_F_LENGTH)
+           throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: >= " + FLAGS_F_LENGTH + ".");
+
+       final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(valueBytes, 0, FLAGS_F_LENGTH));
+       return new PCEStatefulCapabilityTlv(flags.get(I_FLAG_OFFSET), flags.get(U_FLAG_OFFSET), flags.get(S_FLAG_OFFSET));
+    }
+
+    public static byte[] serializeValueField(PCEStatefulCapabilityTlv objToSerialize) {
+       if (objToSerialize == null)
+           throw new IllegalArgumentException("PCEStatefulCapabilityTlv is mandatory.");
+
+       final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+       flags.set(I_FLAG_OFFSET, objToSerialize.isInstantiated());
+       flags.set(U_FLAG_OFFSET, objToSerialize.isUpdate());
+       flags.set(S_FLAG_OFFSET, objToSerialize.isVersioned());
+
+       return ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH);
+    }
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/RSVPErrorSpecIPv4TlvParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/RSVPErrorSpecIPv4TlvParser.java
new file mode 100644 (file)
index 0000000..bcb0e45
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.tlv;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv RSVPErrorSpecTlv}
+ * parameterized as IPv4Address
+ */
+public class RSVPErrorSpecIPv4TlvParser {
+
+       private static final int IP_F_LENGTH = 4;
+       private static final int FLAGS_F_LENGTH = 1;
+       private static final int ERROR_CODE_F_LENGTH = 1;
+       private static final int ERROR_VALUE_F_LENGTH = 2;
+
+       private static final int IP_F_OFFSET = 0;
+       private static final int FLAGS_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+       private static final int ERROR_CODE_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+       private static final int ERROR_VALUE_F_OFFSET = ERROR_CODE_F_OFFSET + ERROR_CODE_F_LENGTH;
+
+       private static final int SIZE = ERROR_VALUE_F_OFFSET + ERROR_VALUE_F_LENGTH;
+
+       /*
+        * flags offsets inside flags field in bits
+        */
+       private static final int IN_PLACE_FLAG_OFFSET = 7;
+       private static final int NOT_GUILTY_FLAGS_OFFSET = 6;
+
+       public static RSVPErrorSpecTlv<IPv4Address> parse(byte[] valueBytes) throws PCEPDeserializerException {
+               if (valueBytes == null || valueBytes.length == 0)
+                       throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+               if (valueBytes.length != SIZE)
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: " + SIZE + ".");
+
+               final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(valueBytes, FLAGS_F_OFFSET, FLAGS_F_LENGTH));
+
+               return new RSVPErrorSpecTlv<IPv4Address>(new IPv4Address(
+                               ByteArray.subByte(valueBytes, IP_F_OFFSET, IP_F_LENGTH)), flags.get(IN_PLACE_FLAG_OFFSET), flags.get(NOT_GUILTY_FLAGS_OFFSET),
+                               valueBytes[ERROR_CODE_F_OFFSET] & 0xFF,
+                               ByteArray.bytesToShort(ByteArray.subByte(valueBytes, ERROR_VALUE_F_OFFSET, ERROR_VALUE_F_LENGTH)) & 0xFFFF);
+       }
+
+       public static byte[] put(RSVPErrorSpecTlv<?> objToSerialize) {
+               if (objToSerialize == null)
+                       throw new IllegalArgumentException("RSVPErrorSpecTlv is mandatory.");
+
+               if (!(((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress() instanceof IPv4Address))
+                       throw new IllegalArgumentException("Unknown parametrized type of RSVPErrorSpecTlv. Passed "
+                                       + ((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress().getClass() + ". Needed IPv4Address.");
+
+               final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+               flags.set(IN_PLACE_FLAG_OFFSET, objToSerialize.isInPlace());
+               flags.set(NOT_GUILTY_FLAGS_OFFSET, objToSerialize.isGuilty());
+
+               final byte[] retBytes = new byte[SIZE];
+
+               ByteArray.copyWhole(((IPv4Address) objToSerialize.getErrorNodeAddress()).getAddress(), retBytes, IP_F_OFFSET);
+               retBytes[ERROR_CODE_F_OFFSET] = ByteArray.intToBytes(objToSerialize.getErrorCode())[Integer.SIZE / Byte.SIZE - 1];
+               System.arraycopy(ByteArray.intToBytes(objToSerialize.getErrorValue()), Integer.SIZE / Byte.SIZE - ERROR_VALUE_F_LENGTH, retBytes, ERROR_VALUE_F_OFFSET,
+                               ERROR_VALUE_F_LENGTH);
+               ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/RSVPErrorSpecIPv6TlvParser.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/tlv/RSVPErrorSpecIPv6TlvParser.java
new file mode 100644 (file)
index 0000000..6a2b8c6
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.tlv;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv RSVPErrorSpecTlv}
+ * parameterized as IPv6Address
+ */
+public class RSVPErrorSpecIPv6TlvParser {
+
+       private static final int IP_F_LENGTH = 16;
+       private static final int FLAGS_F_LENGTH = 1;
+       private static final int ERROR_CODE_F_LENGTH = 1;
+       private static final int ERROR_VALUE_F_LENGTH = 2;
+
+       private static final int IP_F_OFFSET = 0;
+       private static final int FLAGS_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+       private static final int ERROR_CODE_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+       private static final int ERROR_VALUE_F_OFFSET = ERROR_CODE_F_OFFSET + ERROR_CODE_F_LENGTH;
+
+       private static final int SIZE = ERROR_VALUE_F_OFFSET + ERROR_VALUE_F_LENGTH;
+
+       /*
+        * flags offsets inside flags field in bits
+        */
+       private static final int IN_PLACE_FLAG_OFFSET = 7;
+       private static final int NOT_GUILTY_FLAGS_OFFSET = 6;
+
+       public static RSVPErrorSpecTlv<IPv6Address> parse(byte[] valueBytes) throws PCEPDeserializerException {
+               if (valueBytes == null || valueBytes.length == 0)
+                       throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+               if (valueBytes.length != SIZE) {
+                       throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: " + SIZE + ".");
+               }
+
+               final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(valueBytes, FLAGS_F_OFFSET, FLAGS_F_LENGTH));
+
+               return new RSVPErrorSpecTlv<IPv6Address>(new IPv6Address(
+                               ByteArray.subByte(valueBytes, IP_F_OFFSET, IP_F_LENGTH)), flags.get(IN_PLACE_FLAG_OFFSET), flags.get(NOT_GUILTY_FLAGS_OFFSET),
+                               valueBytes[ERROR_CODE_F_OFFSET] & 0xFF,
+                               ByteArray.bytesToShort(ByteArray.subByte(valueBytes, ERROR_VALUE_F_OFFSET, ERROR_VALUE_F_LENGTH)) & 0xFFFF);
+       }
+
+       public static byte[] put(RSVPErrorSpecTlv<?> objToSerialize) {
+               if (objToSerialize == null)
+                       throw new IllegalArgumentException("RSVPErrorSpecTlv is mandatory.");
+
+               if (!(((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress() instanceof IPv6Address))
+                       throw new IllegalArgumentException("Unknown parametrized type of RSVPErrorSpecTlv. Passed "
+                                       + ((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress().getClass() + ". Needed IPv6Address.");
+
+               final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+               flags.set(IN_PLACE_FLAG_OFFSET, objToSerialize.isInPlace());
+               flags.set(NOT_GUILTY_FLAGS_OFFSET, objToSerialize.isGuilty());
+
+               final byte[] retBytes = new byte[SIZE];
+
+               ByteArray.copyWhole(((IPv6Address) objToSerialize.getErrorNodeAddress()).getAddress(), retBytes, IP_F_OFFSET);
+               retBytes[ERROR_CODE_F_OFFSET] = ByteArray.intToBytes(objToSerialize.getErrorCode())[Integer.SIZE / Byte.SIZE - 1];
+               System.arraycopy(ByteArray.intToBytes(objToSerialize.getErrorValue()), Integer.SIZE / Byte.SIZE - ERROR_VALUE_F_LENGTH, retBytes, ERROR_VALUE_F_OFFSET,
+                               ERROR_VALUE_F_LENGTH);
+               ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+               return retBytes;
+       }
+
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/CompositeTest.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/CompositeTest.java
new file mode 100644 (file)
index 0000000..afe67b4
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.CompositePathObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+import org.opendaylight.protocol.pcep.object.CompositeRptPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+import org.opendaylight.protocol.pcep.object.PCEPClassTypeObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import org.opendaylight.protocol.pcep.tlv.LSPCleanupTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+
+public class CompositeTest {
+
+    public PCEPExplicitRouteObject ero;
+    public PCEPClassTypeObject ct;
+    public PCEPLspaObject lspa;
+    public List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+    public PCEPIncludeRouteObject iro = new PCEPIncludeRouteObject(new ArrayList<ExplicitRouteSubobject>() {
+       private static final long serialVersionUID = 1L;
+
+       {
+           this.add(new EROAsNumberSubobject(new ASNumber(0L), true));
+       }
+    }, false, false);
+    public PCEPRequestParameterObject requestParameter;
+    public PCEPNoPathObject noPath;
+    public PCEPRequestedPathBandwidthObject bandwidth;
+
+    public List<PCEPRequestParameterObject> requestParameters = new ArrayList<PCEPRequestParameterObject>();
+    public PCEPErrorObject error;
+    public List<PCEPErrorObject> errors = new ArrayList<PCEPErrorObject>();
+
+    public PCEPNotificationObject notification;
+    public List<PCEPNotificationObject> notifications = new ArrayList<PCEPNotificationObject>();
+
+    private PCEPReportedRouteObject reportedRoute;
+    private PCEPExistingPathBandwidthObject rroBandwidth;
+    private PCEPIncludeRouteObject includeRoute;
+    private PCEPLoadBalancingObject loadBalancing;
+    private PCEPEndPointsObject<?> endPoints;
+
+    private PCEPLspObject lsp;
+    private final List<CompositePathObject> compositePaths = new ArrayList<CompositePathObject>();
+    private final List<CompositeRptPathObject> compositeRptPaths = new ArrayList<CompositeRptPathObject>();
+    private final List<CompositeUpdPathObject> compositeUpdPaths = new ArrayList<CompositeUpdPathObject>();
+    public PCEPReportedRouteObject rro = new PCEPReportedRouteObject(new ArrayList<ReportedRouteSubobject>() {
+       private static final long serialVersionUID = 1L;
+
+       {
+           this.add(new RROAsNumberSubobject(new ASNumber(0L)));
+       }
+    }, false);
+
+    @Before
+    public void setUp() {
+       this.ero = new PCEPExplicitRouteObject(new ArrayList<ExplicitRouteSubobject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new EROAsNumberSubobject(new ASNumber(0L), true));
+           }
+       }, false);
+       this.ct = new PCEPClassTypeObject((short) 5);
+       this.lspa = new PCEPLspaObject(0, 0, 0, (short) 0, (short) 0, false, false, false, false);
+       this.metrics.add(new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+       this.metrics.add(new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+
+       this.requestParameter = new PCEPRequestParameterObject(false, false, false, false, false, false, false, false, (short) 0, 0, false, false);
+       this.noPath = new PCEPNoPathObject((short) 2, false, false);
+       this.bandwidth = new PCEPRequestedPathBandwidthObject(new Bandwidth(0), false, false);
+
+       this.requestParameters.add(this.requestParameter);
+       this.requestParameters.add(this.requestParameter);
+
+       this.error = new PCEPErrorObject(PCEPErrors.BANDWIDTH_MISSING);
+
+       this.errors.add(this.error);
+       this.errors.add(this.error);
+       this.errors.add(this.error);
+
+       this.notification = new PCEPNotificationObject((short) 1, (short) 1);
+
+       this.notifications.add(this.notification);
+       this.notifications.add(this.notification);
+
+       final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>();
+       eroSubobjects.add(new EROAsNumberSubobject(new ASNumber(0x0L), false));
+       eroSubobjects.add(new EROAsNumberSubobject(new ASNumber(0x0L), false));
+       eroSubobjects.add(new EROAsNumberSubobject(new ASNumber(0x0L), false));
+
+       final List<ReportedRouteSubobject> rroSubobjects = new ArrayList<ReportedRouteSubobject>();
+       rroSubobjects.add(new RROAsNumberSubobject(new ASNumber(0x0L)));
+       rroSubobjects.add(new RROAsNumberSubobject(new ASNumber(0x0L)));
+       rroSubobjects.add(new RROAsNumberSubobject(new ASNumber(0x0L)));
+
+       this.reportedRoute = new PCEPReportedRouteObject(rroSubobjects, true);
+       this.rroBandwidth = new PCEPExistingPathBandwidthObject(new Bandwidth(Float.intBitsToFloat(0xFF)), true, false);
+       this.includeRoute = new PCEPIncludeRouteObject(eroSubobjects, true, false);
+       this.loadBalancing = new PCEPLoadBalancingObject(0x0, new Bandwidth(Float.intBitsToFloat(0x0)), false);
+       final byte[] ipbytes = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+       this.endPoints = new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipbytes), new IPv4Address(ipbytes));
+
+       this.lsp = new PCEPLspObject(0, false, false, true, true, null);
+       this.compositePaths.add(new CompositePathObject(new PCEPExplicitRouteObject(eroSubobjects, true), this.lspa, this.bandwidth, this.metrics,
+               this.includeRoute));
+       this.compositePaths.add(new CompositePathObject(new PCEPExplicitRouteObject(eroSubobjects, true)));
+
+       this.compositeUpdPaths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(eroSubobjects, true), this.lspa, this.bandwidth, this.metrics));
+       this.compositeUpdPaths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(eroSubobjects, true)));
+
+    }
+
+    @Test
+    public void testCompositePathObject() {
+       final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+       objects.add(this.ero);
+       objects.add(this.lspa);
+       objects.add(this.metrics.get(0));
+       objects.add(this.metrics.get(1));
+       objects.add(this.iro);
+       objects.add(new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+       final CompositePathObject path = CompositePathObject.getCompositeFromList(objects);
+       assertEquals(path.getExcludedRoute(), this.ero);
+       assertEquals(path.getLspa(), this.lspa);
+       assertNull(path.getBandwidth());
+       assertEquals(path.getMetrics().get(0), this.metrics.get(0));
+       assertEquals(path.getMetrics().get(1), this.metrics.get(1));
+       assertEquals(path.getIncludeRoute(), this.iro);
+    }
+
+    @Test
+    public void testCompositeRptPathObject() {
+       final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+       objects.add(this.ero);
+       objects.add(this.lspa);
+       objects.add(this.rro);
+       objects.add(this.metrics.get(0));
+       objects.add(this.metrics.get(1));
+       objects.add(new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+       final CompositeRptPathObject path = CompositeRptPathObject.getCompositeFromList(objects);
+       assertEquals(path.getExcludedRoute(), this.ero);
+       assertEquals(path.getLspa(), this.lspa);
+       assertNull(path.getBandwidth());
+       assertEquals(path.getMetrics().get(0), this.metrics.get(0));
+       assertEquals(path.getMetrics().get(1), this.metrics.get(1));
+       assertEquals(path.getReportedRoute(), this.rro);
+    }
+
+    @Test
+    public void testCompositeResponseObject() {
+       final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+       objects.add(this.requestParameter);
+       objects.add(this.noPath);
+       objects.add(this.bandwidth);
+       objects.add(this.metrics.get(0));
+       objects.add(this.metrics.get(1));
+       objects.add(this.iro);
+       // add one path
+       objects.add(this.ero);
+       objects.add(this.lspa);
+       objects.add(this.metrics.get(0));
+       objects.add(this.metrics.get(1));
+       objects.add(this.iro);
+       // add another path
+       objects.add(this.ero);
+       objects.add(this.lspa);
+       objects.add(this.metrics.get(0));
+       objects.add(new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+       objects.add(this.iro);
+       //
+       objects.add(this.requestParameter);
+       final List<CompositeResponseObject> list = new ArrayList<CompositeResponseObject>();
+       while (!objects.isEmpty()) {
+           list.add(CompositeResponseObject.getCompositeFromList(objects));
+       }
+       assertEquals(2, list.size());
+       final CompositeResponseObject response = list.get(0);
+
+       assertEquals(response.getRequestParameter(), this.requestParameter);
+       assertEquals(response.getNoPath(), this.noPath);
+       assertNull(response.getLspa());
+       assertEquals(response.getBandwidth(), this.bandwidth);
+       assertEquals(response.getMetrics().get(0), this.metrics.get(0));
+       assertEquals(response.getMetrics().get(1), this.metrics.get(1));
+       assertEquals(response.getIncludeRoute(), this.iro);
+       // check path
+       CompositePathObject path = response.getPaths().get(0);
+       assertEquals(path.getExcludedRoute(), this.ero);
+       assertEquals(path.getLspa(), this.lspa);
+       assertNull(path.getBandwidth());
+       assertEquals(path.getMetrics().get(0), this.metrics.get(0));
+       assertEquals(path.getMetrics().get(1), this.metrics.get(1));
+       assertEquals(path.getIncludeRoute(), this.iro);
+       // check path
+       path = response.getPaths().get(1);
+       assertEquals(path.getExcludedRoute(), this.ero);
+       assertEquals(path.getLspa(), this.lspa);
+       assertNull(path.getBandwidth());
+       assertEquals(path.getMetrics().get(0), this.metrics.get(0));
+       assertEquals(path.getMetrics().get(1), new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+       assertEquals(path.getIncludeRoute(), this.iro);
+    }
+
+    @Test
+    public void testCompositeErrorObject() {
+       final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+       CompositeErrorObject compositeErrors;
+
+       objects.addAll(this.requestParameters);
+       objects.addAll(this.errors);
+       compositeErrors = new CompositeErrorObject(this.requestParameters.subList(0, this.requestParameters.size()), this.errors.subList(0, this.errors.size()));
+       assertEquals(compositeErrors, CompositeErrorObject.getCompositeFromList(objects));
+
+       objects.clear();
+       objects.addAll(this.errors);
+       compositeErrors = new CompositeErrorObject(null, this.errors.subList(0, this.errors.size()));
+       assertEquals(compositeErrors, CompositeErrorObject.getCompositeFromList(objects));
+
+    }
+
+    @Test
+    public void testCompositeNotifyObject() {
+       final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+       CompositeNotifyObject compositeNotifications;
+
+       objects.addAll(this.requestParameters);
+       objects.addAll(this.notifications);
+       compositeNotifications = new CompositeNotifyObject(this.requestParameters.subList(0, this.requestParameters.size()), this.notifications.subList(0,
+               this.notifications.size()));
+       assertEquals(compositeNotifications, CompositeNotifyObject.getCompositeFromList(objects));
+
+       objects.clear();
+       // first
+       objects.addAll(this.requestParameters);
+       objects.addAll(this.notifications);
+       // second
+       objects.addAll(this.requestParameters);
+       objects.addAll(this.notifications);
+       while (!objects.isEmpty()) {
+           assertEquals(compositeNotifications, CompositeNotifyObject.getCompositeFromList(objects));
+       }
+
+       objects.clear();
+       objects.addAll(this.notifications);
+       compositeNotifications = new CompositeNotifyObject(null, this.notifications.subList(0, this.notifications.size()));
+       assertEquals(compositeNotifications, CompositeNotifyObject.getCompositeFromList(objects));
+
+    }
+
+    @Test
+    public void testCompositeRequestObject() {
+       final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+       CompositeRequestObject compositeRequest;
+
+       objects.add(this.requestParameter);
+       objects.add(this.endPoints);
+       objects.add(this.ct);
+       objects.add(this.lsp);
+       objects.add(this.lspa);
+       objects.add(this.bandwidth);
+       objects.addAll(this.metrics);
+       objects.add(this.reportedRoute);
+       objects.add(this.rroBandwidth);
+       objects.add(this.includeRoute);
+       objects.add(this.loadBalancing);
+
+       compositeRequest = new CompositeRequestObject(this.requestParameter, this.endPoints, this.ct, this.lsp, this.lspa, this.bandwidth,
+               this.metrics.subList(0, this.metrics.size()), this.reportedRoute, this.rroBandwidth, this.includeRoute, this.loadBalancing);
+       assertEquals(compositeRequest, CompositeRequestObject.getCompositeFromList(objects));
+
+       objects.clear();
+       // first
+       objects.add(this.requestParameter);
+       objects.add(this.endPoints);
+       objects.add(this.ct);
+       objects.add(this.lsp);
+       objects.add(this.lspa);
+       objects.add(this.bandwidth);
+       objects.addAll(this.metrics);
+       objects.add(this.reportedRoute);
+       objects.add(this.rroBandwidth);
+       objects.add(this.includeRoute);
+       objects.add(this.loadBalancing);
+       // second
+       objects.add(this.requestParameter);
+       objects.add(this.endPoints);
+       objects.add(this.ct);
+       objects.add(this.lsp);
+       objects.add(this.lspa);
+       objects.add(this.bandwidth);
+       objects.addAll(this.metrics);
+       objects.add(this.reportedRoute);
+       objects.add(this.rroBandwidth);
+       objects.add(this.includeRoute);
+       objects.add(this.loadBalancing);
+       while (!objects.isEmpty()) {
+           assertEquals(compositeRequest, CompositeRequestObject.getCompositeFromList(objects));
+       }
+
+       objects.clear();
+       objects.add(this.requestParameter);
+       objects.add(this.endPoints);
+       compositeRequest = new CompositeRequestObject(this.requestParameter, this.endPoints);
+       assertEquals(compositeRequest, CompositeRequestObject.getCompositeFromList(objects));
+
+    }
+
+    @Test
+    public void testCompositeStateReportObject() {
+       final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+       CompositeStateReportObject compositeStateReport;
+
+       objects.add(this.lsp);
+       for (final CompositeRptPathObject compositeRptPath : this.compositeRptPaths) {
+           objects.addAll(compositeRptPath.getCompositeAsList());
+       }
+
+       compositeStateReport = new CompositeStateReportObject(this.lsp, this.compositeRptPaths);
+       assertEquals(compositeStateReport, CompositeStateReportObject.getCompositeFromList(objects));
+
+       objects.clear();
+       // first
+       objects.add(this.lsp);
+       for (final CompositeRptPathObject compositeRptPath : this.compositeRptPaths) {
+           objects.addAll(compositeRptPath.getCompositeAsList());
+       }
+       // second
+       objects.add(this.lsp);
+       for (final CompositeRptPathObject compositeRptPath : this.compositeRptPaths) {
+           objects.addAll(compositeRptPath.getCompositeAsList());
+       }
+       while (!objects.isEmpty()) {
+           assertEquals(compositeStateReport, CompositeStateReportObject.getCompositeFromList(objects));
+       }
+
+       objects.clear();
+       objects.add(this.lsp);
+       for (final CompositeRptPathObject compositeRptPath : this.compositeRptPaths) {
+           objects.addAll(compositeRptPath.getCompositeAsList());
+       }
+       compositeStateReport = new CompositeStateReportObject(this.lsp, this.compositeRptPaths);
+       assertEquals(compositeStateReport, CompositeStateReportObject.getCompositeFromList(objects));
+
+    }
+
+    @Test
+    public void testCompositeUpdateRequestObject() {
+       final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+       CompositeUpdateRequestObject compositeStateReport;
+
+       objects.add(this.lsp);
+       for (final CompositeUpdPathObject compositePath : this.compositeUpdPaths) {
+           objects.addAll(compositePath.getCompositeAsList());
+       }
+
+       compositeStateReport = new CompositeUpdateRequestObject(this.lsp, this.compositeUpdPaths);
+       assertEquals(compositeStateReport, CompositeUpdateRequestObject.getCompositeFromList(objects));
+
+       objects.clear();
+       // first
+       objects.add(this.lsp);
+       for (final CompositeUpdPathObject compositePath : this.compositeUpdPaths) {
+           objects.addAll(compositePath.getCompositeAsList());
+       }
+       // second
+       objects.add(this.lsp);
+       for (final CompositeUpdPathObject compositePath : this.compositeUpdPaths) {
+           objects.addAll(compositePath.getCompositeAsList());
+       }
+       while (!objects.isEmpty()) {
+           assertEquals(compositeStateReport, CompositeUpdateRequestObject.getCompositeFromList(objects));
+       }
+
+       objects.clear();
+       objects.add(this.lsp);
+       for (final CompositeUpdPathObject compositePath : this.compositeUpdPaths) {
+           objects.addAll(compositePath.getCompositeAsList());
+       }
+       compositeStateReport = new CompositeUpdateRequestObject(this.lsp, this.compositeUpdPaths);
+       assertEquals(compositeStateReport, CompositeUpdateRequestObject.getCompositeFromList(objects));
+
+    }
+
+       @SuppressWarnings("resource")
+       @Test
+       public void testSessionProposalCheckerFactory() {
+               assertTrue(new PCEPSessionProposalCheckerFactoryImpl().getPreferencesChecker(null).checkSessionCharacteristics(null));
+               assertEquals(new PCEPSessionPreferences(new PCEPOpenObject(30, 120, 0, null)), new PCEPSessionProposalCheckerFactoryImpl().getPreferencesChecker(null).getNewProposal(null));
+       }
+
+       @Test
+       public void testSessionProposalFactory() throws IOException {
+               final PCEPSessionProposalFactoryImpl spf = new PCEPSessionProposalFactoryImpl(10, 2, true, false, true, true, 5);
+               try {
+                       final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>();
+                       tlvs.add(new PCEStatefulCapabilityTlv(true, false, true));
+                       tlvs.add(new LSPCleanupTlv(5));
+                       assertEquals(new PCEPSessionPreferences(new PCEPOpenObject(2, 10, 0, tlvs)), spf.getSessionProposal(null, 0).getProposal());
+               } finally {
+                       spf.close();
+               }
+       }
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/FiniteStateMachineTest.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/FiniteStateMachineTest.java
new file mode 100644 (file)
index 0000000..49f011f
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.ArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class FiniteStateMachineTest {
+
+       private ServerSessionMock serverSession;
+
+       private final SimpleSessionListener serverListener = new SimpleSessionListener();
+
+       private MockPCE client;
+
+       @Before
+       public void setUp() {
+               this.client = new MockPCE();
+               this.serverSession = new ServerSessionMock(this.serverListener, this.client);
+               this.client.addSession(this.serverSession);
+       }
+
+       /**
+        * Both PCEs accept session characteristics. Also tests KeepAliveTimer and
+        * error message and when pce attempts to establish pce session for the 2nd
+        * time.
+        *
+        * @throws InterruptedException
+        */
+       @Test
+       public void testSessionCharsAccBoth() throws InterruptedException {
+               this.serverSession.startSession();
+               assertEquals(1, this.client.getListMsg().size());
+               assertTrue(this.client.getListMsg().get(0) instanceof PCEPOpenMessage);
+               this.client.sendMessage(new PCEPOpenMessage(new PCEPOpenObject(3, 9, 2)));
+               assertEquals(2, this.client.getListMsg().size());
+               assertTrue(this.client.getListMsg().get(1) instanceof PCEPKeepAliveMessage);
+               this.client.sendMessage(new PCEPKeepAliveMessage());
+               synchronized (this.serverListener) {
+                       while (!this.serverListener.up)
+                               try {
+                                       this.serverListener.wait();
+                               } catch (final InterruptedException e) {
+                                       e.printStackTrace();
+                               }
+               }
+               assertTrue(this.serverListener.up);
+//             Thread.sleep(PCEPSessionImpl.KEEP_ALIVE_TIMER_VALUE * 1000);
+//             assertEquals(3, this.client.getListMsg().size());
+//             assertTrue(this.client.getListMsg().get(2) instanceof PCEPKeepAliveMessage); // test of keepalive timer
+               this.client.sendMessage(new PCEPOpenMessage(new PCEPOpenObject(1, 1, 1)));
+               assertEquals(3, this.client.getListMsg().size());
+               assertTrue(this.client.getListMsg().get(2) instanceof PCEPErrorMessage);
+               for (final PCEPMessage m : this.client.getListMsg()) {
+                       if (m instanceof PCEPErrorMessage) {
+                               final PCEPErrorObject obj = ((PCEPErrorMessage) m).getErrorObjects().get(0);
+                               assertEquals(PCEPErrors.ATTEMPT_2ND_SESSION, obj.getError()); // test of error type 9
+                       }
+               }
+       }
+
+       /**
+        * Mock PCE does not accept session characteristics the first time.
+        *
+        * @throws InterruptedException
+        */
+       @Test
+       public void testSessionCharsAccMe() throws InterruptedException {
+               this.serverSession.startSession();
+               this.client.sendMessage(new PCEPOpenMessage(new PCEPOpenObject(4, 9, 2)));
+               assertEquals(2, this.client.getListMsg().size());
+               assertTrue(this.client.getListMsg().get(0) instanceof PCEPOpenMessage);
+               assertTrue(this.client.getListMsg().get(1) instanceof PCEPKeepAliveMessage);
+               this.client.sendErrorMessage(PCEPErrors.NON_ACC_NEG_SESSION_CHAR, new PCEPOpenObject(3, 7, 2, null));
+               assertEquals(3, this.client.getListMsg().size());
+               assertTrue(this.client.getListMsg().get(2) instanceof PCEPOpenMessage);
+               this.client.sendMessage(new PCEPKeepAliveMessage());
+               synchronized (this.serverListener) {
+                       while (!this.serverListener.up)
+                               try {
+                                       this.serverListener.wait();
+                               } catch (final InterruptedException e) {
+                                       e.printStackTrace();
+                               }
+               }
+               assertTrue(this.serverListener.up);
+       }
+
+       /**
+        * Sending different PCEP Message than Open in session establishment phase.
+        *
+        * @throws InterruptedException
+        */
+       @Test
+       public void testErrorOneOne() throws InterruptedException {
+               this.serverSession.startSession();
+               assertEquals(1, this.client.getListMsg().size());
+               assertTrue(this.client.getListMsg().get(0) instanceof PCEPOpenMessage);
+               this.client.sendMessage(new PCEPNotificationMessage(new ArrayList<CompositeNotifyObject>() {
+                       private static final long serialVersionUID = 1L;
+
+                       {
+                               this.add(new CompositeNotifyObject(new ArrayList<PCEPNotificationObject>() {
+                                       private static final long serialVersionUID = 1L;
+
+                                       {
+                                               this.add(new PCEPNotificationObject((short) 1, (short) 1));
+                                       }
+                               }));
+                       }
+               }));
+               for (final PCEPMessage m : this.client.getListMsg()) {
+                       if (m instanceof PCEPErrorMessage) {
+                               final PCEPErrorObject obj = ((PCEPErrorMessage) m).getErrorObjects().get(0);
+                               assertEquals(PCEPErrors.NON_OR_INVALID_OPEN_MSG, obj.getError());
+                       }
+               }
+       }
+
+       /************* Tests commented because of their long duration (tested timers) **************/
+
+       /**
+        * OpenWait timer expired.
+        *
+        * @throws InterruptedException
+        */
+       @Test
+       @Ignore
+       public void testErrorOneTwo() throws InterruptedException {
+               this.serverSession.startSession();
+               assertEquals(1, this.client.getListMsg().size());
+               assertTrue(this.client.getListMsg().get(0) instanceof PCEPOpenMessage);
+               Thread.sleep(PCEPSessionImpl.OPEN_WAIT_TIMER_VALUE * 1000);
+               for (final PCEPMessage m : this.client.getListMsg()) {
+                       if (m instanceof PCEPErrorMessage) {
+                               final PCEPErrorObject obj = ((PCEPErrorMessage) m).getErrorObjects().get(0);
+                               assertEquals(PCEPErrors.NO_OPEN_BEFORE_EXP_OPENWAIT, obj.getError());
+                       }
+               }
+       }
+
+       /**
+        * KeepWaitTimer expired.
+        *
+        * @throws InterruptedException
+        */
+       @Test
+       @Ignore
+       public void testErrorOneSeven() throws InterruptedException {
+               this.serverSession.startSession();
+               assertEquals(1, this.client.getListMsg().size());
+               assertTrue(this.client.getListMsg().get(0) instanceof PCEPOpenMessage);
+               this.client.sendMessage(new PCEPOpenMessage(new PCEPOpenObject(3, 9, 2)));
+               Thread.sleep(PCEPSessionImpl.KEEP_WAIT_TIMER_VALUE * 1000);
+               for (final PCEPMessage m : this.client.getListMsg()) {
+                       if (m instanceof PCEPErrorMessage) {
+                               final PCEPErrorObject obj = ((PCEPErrorMessage) m).getErrorObjects().get(0);
+                               assertEquals(PCEPErrors.NO_MSG_BEFORE_EXP_KEEPWAIT, obj.getError());
+                       }
+               }
+       }
+
+       @Test
+       @Ignore
+       public void testUnknownMessage() throws InterruptedException {
+               this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+               assertEquals(1, this.serverSession.unknownMessagesTimes.size());
+               Thread.sleep(10000);
+               this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+               assertEquals(2, this.serverSession.unknownMessagesTimes.size());
+               Thread.sleep(10000);
+               this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+               assertEquals(3, this.serverSession.unknownMessagesTimes.size());
+               Thread.sleep(20000);
+               this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+               assertEquals(4, this.serverSession.unknownMessagesTimes.size());
+               Thread.sleep(30000);
+               this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+               assertEquals(3, this.serverSession.unknownMessagesTimes.size());
+               Thread.sleep(10000);
+               this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+               assertEquals(3, this.serverSession.unknownMessagesTimes.size());
+               Thread.sleep(5000);
+               this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+               assertEquals(4, this.serverSession.unknownMessagesTimes.size());
+               Thread.sleep(1000);
+               this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+               assertEquals(5, this.serverSession.unknownMessagesTimes.size());
+               Thread.sleep(1000);
+               this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+               synchronized (this.client) {
+                       while (!this.client.down)
+                               try {
+                                       this.client.wait();
+                               } catch (final InterruptedException e) {
+                                       e.printStackTrace();
+                               }
+               }
+               assertTrue(this.client.down);
+       }
+
+       @After
+       public void tearDown() {
+               this.serverSession.close();
+       }
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/MockDispatcher.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/MockDispatcher.java
new file mode 100644 (file)
index 0000000..beaae41
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.io.IOException;
+
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.SessionParent;
+
+/**
+ *
+ */
+public class MockDispatcher implements SessionParent {
+
+       @Override
+       public void onSessionClosed(ProtocolSession session) {
+
+       }
+
+       @Override
+       public void checkOutputBuffer(ProtocolSession session) {
+
+       }
+
+       @Override
+       public void close() throws IOException {
+
+       }
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/MockPCE.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/MockPCE.java
new file mode 100644 (file)
index 0000000..7d9278c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ *
+ */
+public class MockPCE extends PCEPSessionListener {
+
+       private final List<PCEPMessage> listMsg = new ArrayList<PCEPMessage>();
+
+       private PCEPSessionImpl session = null;
+
+       public boolean up = false;
+
+       private static final Logger logger = LoggerFactory.getLogger(MockPCE.class);
+
+       public boolean down = false;
+
+       public MockPCE() {
+       }
+
+       public void sendMessage(PCEPMessage msg) {
+               this.session.handleMessage(msg);
+       }
+
+       public void sendErrorMessage(PCEPErrors value,
+                       PCEPOpenObject open) {
+               final PCEPErrorObject error = new PCEPErrorObject(value);
+               final List<PCEPErrorObject> errors = new ArrayList<PCEPErrorObject>();
+               errors.add(error);
+               this.sendMessage(new PCEPErrorMessage(open, errors, null));
+       }
+
+       public List<PCEPMessage> getListMsg() {
+               return this.listMsg;
+       }
+
+       public void addSession(PCEPSessionImpl l) {
+               this.session = l;
+       }
+
+       @Override
+       public void onMessage(PCEPSession session, PCEPMessage message) {
+               this.listMsg.add(message);
+               logger.debug("Message received:" + message);
+       }
+
+       @Override
+       public void onSessionUp(PCEPSession session, PCEPOpenObject local,
+                       PCEPOpenObject remote) {
+               logger.debug("Session Up");
+               this.up = true;
+               this.notifyAll();
+       }
+
+       @Override
+       public void onSessionDown(PCEPSession session, PCEPCloseObject reason, Exception e) {
+               logger.debug("Session Down");
+               this.down = true;
+               //this.notifyAll();
+       }
+
+       @Override
+       public void onSessionTerminated(PCEPSession session,
+                       TerminationReason cause) {
+               logger.debug("Session terminated. Cause : " + cause.toString());
+       }
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPObjectParserTest.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPObjectParserTest.java
new file mode 100644 (file)
index 0000000..9d9a4f2
--- /dev/null
@@ -0,0 +1,994 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.impl.object.PCEPClassTypeObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPErrorObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPErrorObjectParser.PCEPErrorIdentifier;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.object.PCEPBranchNodeListObject;
+import org.opendaylight.protocol.pcep.object.PCEPClassTypeObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPNonBranchNodeListObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryRecordRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+import org.opendaylight.protocol.pcep.object.PCEPUnreachedDestinationObject;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSubobjectAttribute;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import org.opendaylight.protocol.pcep.tlv.OrderTlv;
+import org.opendaylight.protocol.pcep.tlv.OverloadedDurationTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+
+/**
+ * Used resources<br/>
+ * <br/>
+ * PCEPOpenObject3.bin<br/>
+ * objClass: 1<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * keepAlive: 30<br/>
+ * deadTimer: 120<br/>
+ * sessionId: 1<br/>
+ * tlvs:NO<br/>
+ * <br/>
+ * PCEPBandwidthObject1LowerBounds.bin<br/>
+ * objClass: 5 <br/>
+ * objType: 1<br/>
+ * objLength: 16<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Bandwidth: 0<br/>
+ * <br/>
+ * PCEPBandwidthObject2UpperBounds.bin<br/>
+ * objClass: 5 <br/>
+ * objType: 1<br/>
+ * objLength: 16<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Bandwidth: 0xFFFFFFFF<br/>
+ * <br/>
+ * PCEPEndPointsObject1IPv4.bin<br/>
+ * objClass: 4 <br/>
+ * objType: 1<br/>
+ * objLength: 12<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * src IP: 0xA2F5110E <br/>
+ * dest IP: 0xFFFFFFFF <br/>
+ * <br/>
+ * PCEPEndPointsObject2IPv6.bin<br/>
+ * objClass: 4 <br/>
+ * objType: 2<br/>
+ * objLength: 36<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * src IP: 0xFFFFFFFFF FFFFFFFFF FFFFFFFFF FFFFFFFFF<br/>
+ * dest IP: 0x00025DD2 FFECA1B6 581E9F50 00000000 <br/>
+ * <br/>
+ * PCEPErrorObject1.bin<br/>
+ * objClass: 13 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Error-type: 1<br/>
+ * Error-value: 1<br/>
+ * Tlvs: NO<br/>
+ * <br/>
+ * PCEPErrorObject2Invalid.bin<br/>
+ * objClass: 13 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Error-type: 3<br/>
+ * Error-value: 0<br/>
+ * Tlvs: NO<br/>
+ * <br/>
+ * PCEPErrorObject3.bin<br/>
+ * objClass: 13 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Error-type: 2<br/>
+ * Error-value: 0<br/>
+ * Tlvs: NO<br/>
+ * <br/>
+ * PCEPLspaObject1LowerBounds.bin<br/>
+ * objClass: 9<br/>
+ * objType: 1<br/>
+ * objLength: 20<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Exclude-any: 0x00000000L<br/>
+ * Include-any: 0x00000000L<br/>
+ * Include-all: 0x00000000L<br/>
+ * Setup Prio: 0x00<br/>
+ * Holding Prio: 0x00<br/>
+ * Flags: - L : false<br/>
+ * <br/>
+ * PCEPLspaObject2UpperBounds.bin<br/>
+ * objClass: 9<br/>
+ * objType: 1<br/>
+ * objLength: 20<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Exclude-any: 0xFFFFFFFFL<br/>
+ * Include-any: 0xFFFFFFFFL<br/>
+ * Include-all: 0xFFFFFFFFL<br/>
+ * Setup Prio: 0xFF<br/>
+ * Holding Prio: 0xFF<br/>
+ * Flags: - L : true<br/>
+ * <br/>
+ * PCEPLspaObject3RandVals.bin<br/>
+ * objClass: 9<br/>
+ * objType: 1<br/>
+ * objLength: 20<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Exclude-any: 0x20A1FEE3L<br/>
+ * Include-any: 0x1A025CC7L<br/>
+ * Include-all: 0x2BB66532L<br/>
+ * Setup Prio: 0x03<br/>
+ * Holding Prio: 0x02<br/>
+ * Flags: - L : true<br/>
+ * <br/>
+ * NoPathObject1WithTLV.bin<br/>
+ * objClass: 3 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 16<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Nature of Issue: 2<br/>
+ * No-Path flags:<br/>
+ * - C: true<br/>
+ * <br/>
+ * tlvs:<br/>
+ * -- NO-PATH-VECTOR<br/>
+ * - flags (0x4000):<br/>
+ * - PCE currently unavailable: false<br/>
+ * - unknown destination: true<br/>
+ * - unknown source: false<br/>
+ *
+ * <br/>
+ * NoPathObject2WithoutTLV.bin<br/>
+ * objClass: 3 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Nature of Issue: 16<br/>
+ * No-Path flags:<br/>
+ * - C: false<br/>
+ * <br/>
+ * tlvs:NO<br/>
+ * <br/>
+ * PCEPNotificationObject1WithTlv.bin <br/>
+ * objClass: 12<br/>
+ * objType: 1<br/>
+ * objLength: 16<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * NT: 1<br/>
+ * NV: 1<br/>
+ * Tlvs:<br/>
+ * - OverloaderDuration(0xFF0000A2L)<br/>
+ * <br/>
+ * PCEPNotificationObject2WithoutTlv.bin <br/>
+ * objClass: 12<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * NT: 0xFF<br/>
+ * NV: 0xFF<br/>
+ * Tlvs: NO<br/>
+ * <br/>
+ * PCEPOpenObject1.bin<br/>
+ * objClass: 1<br/>
+ * objType: 1<br/>
+ * objLength: 28<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * keepAlive: 30<br/>
+ * deadTimer: 120<br/>
+ * sessionId: 1<br/>
+ * tlvs:<br/>
+ * - PCEPStatefulCapability<br/>
+ * - LSPStateDBVersionTlv<br/>
+ * - NodeIdentifierTlv<br/>
+ * <br/>
+ * PCEPOpenObject2UpperBoundsNoTlv.bin<br/>
+ * objClass: 1<br/>
+ * objType: 1<br/>
+ * objLength: 34<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * keepAlive: 0xFF<br/>
+ * deadTimer: 0xFF<br/>
+ * sessionId: 0xFF<br/>
+ * tlvs: NO<br/>
+ * <br/>
+ * PCEPRPObject1.bin<br/>
+ * objClass: 2 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 12<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * RP flags:<br/>
+ * - loose/strict: true<br/>
+ * - Bi-directional: false<br/>
+ * - Reoptimization: false<br/>
+ * - Priority: 5<br/>
+ * Request ID: 0xDEADBEEF<br/>
+ * tlvs: NO<br/>
+ * <br/>
+ * PCEPSvecObject1_10ReqIDs.bin <br/>
+ * objClass: 11<br/>
+ * objType: 1<br/>
+ * objLength: 48<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Flags:<br/>
+ * - Link diverse: true<br/>
+ * - Node diverse: false<br/>
+ * - SRLG diverse: true<br/>
+ * Reques-ID-numbers:<br/>
+ * #1 - 0xFFFFFFFFL<br/>
+ * #2 - 0x00000000L<br/>
+ * #3 - 0x01234567L<br/>
+ * #4 - 0x89ABCDEFL<br/>
+ * #5 - 0xFEDCBA98L<br/>
+ * #6 - 0x76543210L<br/>
+ * #7 - 0x15825266L<br/>
+ * #8 - 0x48120BBEL<br/>
+ * #9 - 0x25FB7E52L<br/>
+ * #10 - 0xB2F2546BL<br/>
+ * <br/>
+ * PCEPSvecObject2.bin <br/>
+ * objClass: 11<br/>
+ * objType: 1<br/>
+ * objLength: 08<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Flags:<br/>
+ * - Link diverse: false<br/>
+ * - Node diverse: false<br/>
+ * - SRLG diverse: false<br/>
+ * Reques-ID-numbers:<br/>
+ * #1 - 0x000000FFL<br/>
+ * PCEPExcludeRouteObject.1.bin <br/>
+ * objClass: 17 <br/>
+ * objType: 1 <br/>
+ * objLength: 20 <br/>
+ * version: 1 <br/>
+ * Flags: <br/>
+ * - fail: true <br/>
+ * Subobjects: <br/>
+ * - XROIPv4PreffixSubobject(192.168.0.0/16, exclude, node) <br/>
+ * - XROASnumber(0x1234) <br/>
+ */
+
+public class PCEPObjectParserTest {
+
+       IPv4Address ipv4addr = new IPv4Address(new byte[] { (byte) 192, (byte) 168, 1, 8 });
+
+       IPv6Address ipv6addr = new IPv6Address(new byte[] { (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168,
+                       2, 1, (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168, 2, 1 });
+
+       @SuppressWarnings("unchecked")
+       private static <T extends PCEPObject> void serDeserTest(final String srcFile, final T specObject) throws IOException,
+                       PCEPDeserializerException, PCEPDocumentedException {
+               final byte[] bytesFromFile = ByteArray.fileToBytes(srcFile);
+               final T deserSpecObj = (T) PCEPObjectFactory.parseObjects(bytesFromFile).get(0);
+               final byte[] serSpecObj = PCEPObjectFactory.put(Arrays.asList((PCEPObject) specObject));
+
+               assertEquals(specObject, deserSpecObj);
+               assertArrayEquals(bytesFromFile, serSpecObj);
+       }
+
+       /**
+        * Standard serialization test<br/>
+        * Used resources:<br/>
+        * - PCEPOpenObject1.bin<br/>
+        *
+        * @throws PCEPDeserializerException
+        * @throws IOException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       @Ignore //FIXME: temporary
+       public void testObjectDeserialization() throws PCEPDeserializerException, IOException,
+                       PCEPDocumentedException {
+               PCEPObjectFactory.parseObjects(ByteArray.fileToBytes("src/test/resources/PCEPOpenObject1.bin"));
+       }
+
+       @Test
+       public void testUnknownClass() throws PCEPDeserializerException, IOException, PCEPDocumentedException {
+
+               final PCEPObject obj = PCEPObjectFactory.parseObjects(
+                               ByteArray.fileToBytes("src/test/resources/PCEPObject1UnknownClass.bin")).get(0);
+
+               assertTrue(obj instanceof UnknownObject);
+               assertEquals(((UnknownObject) obj).getError(), PCEPErrors.UNRECOGNIZED_OBJ_CLASS);
+       }
+
+       @Test
+       public void testUnknownType() throws PCEPDeserializerException, IOException, PCEPDocumentedException {
+               final PCEPObject obj = PCEPObjectFactory.parseObjects(
+                               ByteArray.fileToBytes("src/test/resources/PCEPObject2UnknownType.bin")).get(0);
+
+               assertTrue(obj instanceof UnknownObject);
+               assertEquals(((UnknownObject) obj).getError(), PCEPErrors.UNRECOGNIZED_OBJ_TYPE);
+       }
+
+       @Test
+       public void testCloseObjSerDeser() throws IOException, PCEPDeserializerException, PCEPDocumentedException {
+               serDeserTest("src/test/resources/PCEPCloseObject1.bin", new PCEPCloseObject(
+                               Reason.TOO_MANY_UNKNOWN_MSG));
+       }
+
+       @Test
+       public void testLoadBalancingObjSerDeser() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               serDeserTest("src/test/resources/PCEPLoadBalancingObject1.bin", new PCEPLoadBalancingObject(0xF1,
+                               new Bandwidth(Float.intBitsToFloat(0xFFFFFFFF)), true));
+       }
+
+       @Test
+       public void testLspObjectSerDeser() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               serDeserTest("src/test/resources/PCEPLspObject1NoTlvsUpperBounds.bin", new PCEPLspObject(0xFFFFF,
+                               true, false, true, false, null));
+       }
+
+       @Test
+       public void testERObjectSerDeser() throws IOException, PCEPDeserializerException, PCEPDocumentedException {
+               final byte[] bytesFromFile = ByteArray
+                               .fileToBytes("src/test/resources/PCEPExplicitRouteObject1PackOfSubobjects.bin");
+
+               final PCEPExplicitRouteObject specObj = (PCEPExplicitRouteObject) PCEPObjectFactory.parseObjects(
+                               bytesFromFile).get(0);
+
+               assertEquals(8, specObj.getSubobjects().size());
+
+               final byte[] bytesActual = PCEPObjectFactory.put(Arrays.asList((PCEPObject) specObj));
+               assertArrayEquals(bytesFromFile, bytesActual);
+       }
+
+       @Test
+       public void testIRObjectSerDeser() throws IOException, PCEPDeserializerException, PCEPDocumentedException {
+               final byte[] bytesFromFile = ByteArray
+                               .fileToBytes("src/test/resources/PCEPIncludeRouteObject1PackOfSubobjects.bin");
+
+               final PCEPIncludeRouteObject specObj = (PCEPIncludeRouteObject) PCEPObjectFactory.parseObjects(
+                               bytesFromFile).get(0);
+
+               assertEquals(8, specObj.getSubobjects().size());
+
+               final byte[] bytesActual = PCEPObjectFactory.put(Arrays.asList((PCEPObject) specObj));
+               assertArrayEquals(bytesFromFile, bytesActual);
+       }
+
+       @Test
+       public void tesRRObjectSerDeser() throws IOException, PCEPDeserializerException, PCEPDocumentedException {
+               final byte[] bytesFromFile = ByteArray
+                               .fileToBytes("src/test/resources/PCEPReportedRouteObject1PackOfSubobjects.bin");
+
+               final PCEPReportedRouteObject specObj = (PCEPReportedRouteObject) PCEPObjectFactory.parseObjects(
+                               bytesFromFile).get(0);
+
+               assertEquals(6, specObj.getSubobjects().size());
+
+               final byte[] bytesActual = PCEPObjectFactory.put(Arrays.asList((PCEPObject) specObj));
+               assertArrayEquals(bytesFromFile, bytesActual);
+       }
+
+       /**
+        * Test for upper/lower bounds (Serialization/Deserialization)<br/>
+        * Used resources:<br/>
+        * - PCEPBandwidthObject2UpperBounds.bin<br/>
+        * - PCEPBandwidthObject1LowerBounds.bin<br/>
+        *
+        * @throws IOException
+        * @throws PCEPDeserializerException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testBandwidthObjectBounds() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               final byte[] bytesFloat = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+               serDeserTest("src/test/resources/PCEPBandwidthObject2UpperBounds.bin",
+                               new PCEPRequestedPathBandwidthObject(new Bandwidth(ByteArray.bytesToFloat(bytesFloat)), true,
+                                               true));
+               serDeserTest("src/test/resources/PCEPBandwidthObject1LowerBounds.bin",
+                               new PCEPRequestedPathBandwidthObject(new Bandwidth(0), true, true));
+       }
+
+       /**
+        * Test for upper/lower bounds of IPv4 EndPoints
+        * (Serialization/Deserialization)<br/>
+        * Used resources:<br/>
+        * - PCEPEndPointsObject1IPv4.bin<br/>
+        *
+        * @throws IOException
+        * @throws PCEPDeserializerException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testEndPointsObjectSerDeserIPv4() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               final byte[] srcIPBytes = { (byte) 0xA2, (byte) 0xF5, (byte) 0x11, (byte) 0x0E };
+               final byte[] destIPBytes = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+               serDeserTest("src/test/resources/PCEPEndPointsObject1IPv4.bin", new PCEPEndPointsObject<IPv4Address>(
+                               new IPv4Address(srcIPBytes), new IPv4Address(destIPBytes)));
+       }
+
+       /**
+        * Test for upper/lower bounds of IPv6 EndPoints
+        * (Serialization/Deserialization)<br/>
+        * Used resources:<br/>
+        * - PCEPEndPointsObject2IPv6.bin<br/>
+        *
+        * @throws IOException
+        * @throws PCEPDeserializerException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testEndPointsObjectSerDeserIPv6() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               final byte[] destIPBytes = { (byte) 0x00, (byte) 0x02, (byte) 0x5D, (byte) 0xD2, (byte) 0xFF,
+                               (byte) 0xEC, (byte) 0xA1, (byte) 0xB6, (byte) 0x58, (byte) 0x1E, (byte) 0x9F, (byte) 0x50,
+                               (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, };
+               final byte[] srcIPBytes = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+                               (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+                               (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+
+               serDeserTest("src/test/resources/PCEPEndPointsObject2IPv6.bin", new PCEPEndPointsObject<IPv6Address>(
+                               new IPv6Address(srcIPBytes), new IPv6Address(destIPBytes)));
+       }
+
+       /**
+        * Test of Serialization/Deserialization of PCEPErrorObjectParser.<br/>
+        * <br/>
+        * Used resources:<br/>
+        * - PCEPErrorObject1.bin<br/>
+        * - PCEPErrorObject3.bin<br/>
+        *
+        * @throws PCEPDeserializerException
+        * @throws IOException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testErrorObjectSerDeserWithTlv() throws PCEPDeserializerException, IOException,
+                       PCEPDocumentedException {
+               serDeserTest("src/test/resources/PCEPErrorObject1.bin", new PCEPErrorObject(
+                               PCEPErrors.NON_OR_INVALID_OPEN_MSG));
+               serDeserTest("src/test/resources/PCEPErrorObject3.bin", new PCEPErrorObject(
+                               PCEPErrors.CAPABILITY_NOT_SUPPORTED));
+       }
+
+       /**
+        * Test of validity of PCEPErrorObjectParser. Expect throwed
+        * NoSuchElementException.<br/>
+        * <br/>
+        * Used resources:<br/>
+        * - PCEPErrorObject2Invalid.bin<br/>
+        *
+        * @throws NoSuchElementException
+        * @throws IOException
+        * @throws PCEPDocumentedException
+        */
+       @Test(expected = PCEPDeserializerException.class)
+       public void testUnknownError() throws PCEPDeserializerException, IOException, PCEPDocumentedException {
+               PCEPObjectFactory.parseObjects(
+                               ByteArray.fileToBytes("src/test/resources/PCEPErrorObject2Invalid.bin")).get(0);
+       }
+
+       /**
+        * Test for upper/lower bounds of PCEPLspaObject
+        * (Serialization/Deserialization)<br/>
+        * Used resources:<br/>
+        * - PCEPLspaObject1LowerBounds.bin<br/>
+        * - PCEPLspaObject2UpperBounds.bin<br/>
+        * - PCEPLspaObject3RandVals.bin<br/>
+        *
+        * @throws IOException
+        * @throws PCEPDeserializerException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testLspaObjectSerDeser() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               serDeserTest("src/test/resources/PCEPLspaObject2UpperBounds.bin", new PCEPLspaObject(0xFFFFFFFFL,
+                               0xFFFFFFFFL, 0xFFFFFFFFL, (short) 0xFF, (short) 0xFF, false, true, true, true));
+               serDeserTest("src/test/resources/PCEPLspaObject1LowerBounds.bin", new PCEPLspaObject(0x00000000L,
+                               0x00000000L, 0x00000000L, (short) 0x00, (short) 0x00, false, false, true, true));
+               serDeserTest("src/test/resources/PCEPLspaObject3RandVals.bin", new PCEPLspaObject(0x20A1FEE3L,
+                               0x1A025CC7L, 0x2BB66532L, (short) 0x03, (short) 0x02, false, true, true, true));
+       }
+
+       @Test
+       public void testMetricObjectSerDeserBounds() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               final byte[] bytesFromFileUB = ByteArray
+                               .fileToBytes("src/test/resources/PCEPMetricObject2UpperBounds.bin");
+               final byte[] bytesFromFileLB = ByteArray
+                               .fileToBytes("src/test/resources/PCEPMetricObject1LowerBounds.bin");
+
+               final PCEPMetricObject metricObjectLB = (PCEPMetricObject) PCEPObjectFactory.parseObjects(
+                               bytesFromFileLB).get(0);
+               final PCEPMetricObject metricObjectUB = (PCEPMetricObject) PCEPObjectFactory.parseObjects(
+                               bytesFromFileUB).get(0);
+
+               assertEquals(new PCEPMetricObject(false, false, new IGPMetric(0), true, true), metricObjectLB);
+               assertEquals(new PCEPMetricObject(false, true, new TEMetric(4026531840L), true, true), metricObjectUB);
+
+               final byte[] bytesActualLB = PCEPObjectFactory.put(Arrays.asList((PCEPObject) metricObjectLB));
+               final byte[] bytesActualUB = PCEPObjectFactory.put(Arrays.asList((PCEPObject) metricObjectUB));
+               assertArrayEquals(bytesFromFileLB, bytesActualLB);
+               assertArrayEquals(bytesFromFileUB, bytesActualUB);
+       }
+
+       /**
+        * Standard deserialization test + specific test without tlv<br/>
+        * Used resources:<br/>
+        * - NoPathObject1WithTLV.bin<br/>
+        * - NoPathObject2WithoutTLV.bin<br/>
+        *
+        * @throws PCEPDeserializerException
+        * @throws IOException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testNoPathObjectDeserialization() throws PCEPDeserializerException, IOException,
+                       PCEPDocumentedException {
+               final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>(1);
+               tlvs.add(new NoPathVectorTlv(false, false, true, false, false, false));
+               serDeserTest("src/test/resources/NoPathObject1WithTLV.bin", new PCEPNoPathObject((short) 2, true,
+                               tlvs, false));
+               serDeserTest("src/test/resources/NoPathObject2WithoutTLV.bin", new PCEPNoPathObject((short) 0x10,
+                               false, true));
+
+       }
+
+       /**
+        * Standard serialization test + without tlv<br/>
+        * Used resources:<br/>
+        * - NoPathObject1WithTLV.bin<br/>
+        * - NoPathObject2WithoutTLV.bin<br/>
+        *
+        * @throws PCEPDeserializerException
+        * @throws IOException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testNoPathObjectSerialization() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/NoPathObject2WithoutTLV.bin");
+               PCEPNoPathObject noPathObject = (PCEPNoPathObject) PCEPObjectFactory.parseObjects(bytesFromFile).get(
+                               0);
+               byte[] bytesActual = PCEPObjectFactory.put(Arrays.asList((PCEPObject) noPathObject));
+               assertArrayEquals(bytesFromFile, bytesActual);
+
+               bytesFromFile = ByteArray.fileToBytes("src/test/resources/NoPathObject1WithTLV.bin");
+               noPathObject = (PCEPNoPathObject) PCEPObjectFactory.parseObjects(bytesFromFile).get(0);
+               bytesActual = PCEPObjectFactory.put(Arrays.asList((PCEPObject) noPathObject));
+               assertArrayEquals(bytesFromFile, bytesActual);
+       }
+
+       /**
+        * Specific test with/without tlvs (Ser/Deser)<br/>
+        * Used resources:<br/>
+        * - PCEPNotificationObject1WithTlv.bin -
+        * PCEPNotificationObject2WithoutTlv.bin
+        *
+        * @throws PCEPDeserializerException
+        * @throws IOException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testNotifyObjectSerDeserWithTlv() throws PCEPDeserializerException, IOException,
+                       PCEPDocumentedException {
+               final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>(1);
+               tlvs.add(new OverloadedDurationTlv(0xFF0000A2));
+               serDeserTest("src/test/resources/PCEPNotificationObject1WithTlv.bin", new PCEPNotificationObject(
+                               (short) 1, (short) 1, tlvs));
+               serDeserTest("src/test/resources/PCEPNotificationObject2WithoutTlv.bin", new PCEPNotificationObject(
+                               (short) 0xFF, (short) 0xFF));
+       }
+
+       /**
+        * Standard ser deser test<br/>
+        * used resources:<br/>
+        * - PCEPOpenObject1.bin
+        *
+        * @throws PCEPDeserializerException
+        * @throws IOException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       @Ignore //FIXME: temporary
+       public void testOpenObjectSerDeser() throws PCEPDeserializerException, IOException,
+                       PCEPDocumentedException {
+               final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>();
+               tlvs.add(new PCEStatefulCapabilityTlv(false, true, true));
+               tlvs.add(new LSPStateDBVersionTlv(0x80));
+               final byte[] valueBytes = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9A,
+                               (byte) 0xBC, (byte) 0xDE, (byte) 0xF0 };
+               tlvs.add(new NodeIdentifierTlv(valueBytes));
+               final PCEPOpenObject specObject = new PCEPOpenObject(30, 120, 1, tlvs);
+
+               serDeserTest("src/test/resources/PCEPOpenObject1.bin", specObject);
+       }
+
+       /**
+        * Specific test for upper bounds and without tlvs<br/>
+        * Used resources:<br/>
+        * - PCEPOpenObject2UpperBoundsNoTlv.bin
+        *
+        * @throws PCEPDeserializerException
+        * @throws IOException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testOpenObjectBoundsWithoutTlvs() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>();
+               serDeserTest("src/test/resources/PCEPOpenObject2UpperBoundsNoTlv.bin", new PCEPOpenObject(0xFF, 0xFF,
+                               0xFF, tlvs));
+               serDeserTest("src/test/resources/PCEPOpenObject2UpperBoundsNoTlv.bin", new PCEPOpenObject(0xFF, 0xFF,
+                               0xFF, null));
+       }
+
+       /**
+        * Standard deserialization test<br/>
+        * Used resources:<br/>
+        * - PCEPRPObject1.bin
+        *
+        * @throws PCEPDeserializerException
+        * @throws IOException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testRPObjectSerDeser() throws PCEPDeserializerException, IOException, PCEPDocumentedException {
+               serDeserTest("src/test/resources/PCEPRPObject1.bin", new PCEPRequestParameterObject(true, false,
+                               true, true, false, false, false, false, (short) 5, 0xdeadbeefL, false, false));
+               serDeserTest("src/test/resources/PCEPRPObject2.bin", new PCEPRequestParameterObject(true, false,
+                               false, false, true, false, true, false, true, (short) 5, 0xdeadbeefL,
+                               new ArrayList<PCEPTlv>() {
+                                       private static final long serialVersionUID = 1L;
+
+                                       {
+                                               this.add(new OrderTlv(0xFFFFFFFFL, 0x00000001L));
+                                       }
+                               }, false, false));
+       }
+
+       /**
+        * Test for upper/lower bounds of PCEPSvecObject
+        * (Serialization/Deserialization)<br/>
+        * Used resources:<br/>
+        * - PCEPSvecObject1_10ReqIDs.bin<br/>
+        *
+        * @throws IOException
+        * @throws PCEPDeserializerException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testSvecObjectSerDeser() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               final List<Long> requestIDs = new ArrayList<Long>(10);
+               requestIDs.add(0xFFFFFFFFL);
+               requestIDs.add(0x00000000L);
+               requestIDs.add(0x01234567L);
+               requestIDs.add(0x89ABCDEFL);
+               requestIDs.add(0xFEDCBA98L);
+               requestIDs.add(0x76543210L);
+               requestIDs.add(0x15825266L);
+               requestIDs.add(0x48120BBEL);
+               requestIDs.add(0x25FB7E52L);
+               requestIDs.add(0xB2F2546BL);
+
+               serDeserTest("src/test/resources/PCEPSvecObject1_10ReqIDs.bin", new PCEPSvecObject(true, false, true,
+                               false, true, requestIDs, true));
+       }
+
+       /**
+        * Test for lowest bounds of PCEPSvecObject (Serialization/Deserialization)<br/>
+        * Used resources:<br/>
+        * - PCEPSvecObject2.bin<br/>
+        *
+        * @throws IOException
+        * @throws PCEPDeserializerException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testSvecObjectSerDeserNoReqIDs() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               final List<Long> requestIDs = new ArrayList<Long>();
+               requestIDs.add(0xFFL);
+               serDeserTest("src/test/resources/PCEPSvecObject2.bin", new PCEPSvecObject(false, false, false, false,
+                               false, requestIDs, false));
+       }
+
+       @Test
+       public void testClassTypeObject() throws PCEPDeserializerException, PCEPDocumentedException {
+               final PCEPClassTypeObject ct = new PCEPClassTypeObject((short) 4);
+               final PCEPClassTypeObjectParser parser = new PCEPClassTypeObjectParser();
+               final byte[] bytes = parser.put(ct);
+               assertEquals(ct, parser.parse(bytes, true, false));
+       }
+
+       /**
+        * Test PCEPExcludeRouteObjectObject (Serialization/Deserialization)<br/>
+        * Used resources:<br/>
+        * - PCEPExcludeRouteObject.1.bin<br/>
+        *
+        * @throws IOException
+        * @throws PCEPDeserializerException
+        * @throws PCEPDocumentedException
+        */
+       @Test
+       public void testExcludeRouteObject() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               final List<ExcludeRouteSubobject> xroSubobjects = new ArrayList<ExcludeRouteSubobject>();
+               xroSubobjects.add(new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(new byte[] {
+                               (byte) 192, (byte) 168, (byte) 100, (byte) 100 }), 16), true, XROSubobjectAttribute.NODE));
+               xroSubobjects.add(new XROAsNumberSubobject(new ASNumber(0x1234L), false));
+
+       }
+
+       @Test
+       public void tesObjectiveFunctionObject() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               serDeserTest("src/test/resources/PCEPObjectiveFunctionObject.1.bin", new PCEPObjectiveFunctionObject(
+                               PCEPOFCodes.MBC, true, false));
+       }
+
+       @Test
+       public void tesGlobalConstraintsObject() throws IOException, PCEPDeserializerException,
+                       PCEPDocumentedException {
+               serDeserTest("src/test/resources/PCEPGlobalConstraintsObject.1.bin", new PCEPGlobalConstraintsObject(
+                               (short) 1, (short) 0, (short) 100, (short) 0xFF, true, false));
+       }
+
+       // FIXME: add at least one test with true value
+       @Test
+       public void openObjectWithTlv() throws PCEPDeserializerException, PCEPDocumentedException {
+               this.testOpenObjectWithSpecTlv(new PCEStatefulCapabilityTlv(false, false, false));
+               this.testOpenObjectWithSpecTlv(new PCEStatefulCapabilityTlv(false, false, true));
+               this.testOpenObjectWithSpecTlv(new PCEStatefulCapabilityTlv(false, true, false));
+               this.testOpenObjectWithSpecTlv(new PCEStatefulCapabilityTlv(false, true, true));
+       }
+
+       private void testOpenObjectWithSpecTlv(final PCEPTlv tlv) throws PCEPDeserializerException,
+                       PCEPDocumentedException {
+               final List<PCEPObject> objs = new ArrayList<PCEPObject>();
+               final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>();
+               tlvs.add(tlv);
+               final PCEPOpenObject oo = new PCEPOpenObject(30, 120, 0, tlvs);
+               objs.add(oo);
+               final byte[] bytes = PCEPObjectFactory.put(objs);
+               final PCEPObject obj = PCEPObjectFactory.parseObjects(bytes).get(0);
+               assertEquals(oo, obj);
+       }
+
+       @Test
+       public void testErrorsMapping() {
+               final PCEPErrorObjectParser.PCEPErrorsMaping mapper = PCEPErrorObjectParser.PCEPErrorsMaping
+                               .getInstance();
+
+               for (final PCEPErrors error : PCEPErrors.values()) {
+                       final PCEPErrorIdentifier errorId = mapper.getFromErrorsEnum(error);
+                       assertEquals(error, mapper.getFromErrorIdentifier(errorId));
+               }
+       }
+
+       @Test
+       public void testOFCodesMapping() {
+               final PCEPOFCodesMapping mapper = PCEPOFCodesMapping.getInstance();
+
+               for (final PCEPOFCodes ofCode : PCEPOFCodes.values()) {
+                       final int ofCodeId = mapper.getFromOFCodesEnum(ofCode);
+                       assertEquals(ofCode, mapper.getFromCodeIdentifier(ofCodeId));
+               }
+       }
+
+       @SuppressWarnings("unchecked")
+       private static <T extends PCEPObject> void serDeserTestWithoutBin(final T object)
+                       throws PCEPDeserializerException, PCEPDocumentedException {
+               final byte[] serBytes = PCEPObjectFactory.put(Arrays.asList((PCEPObject) object));
+               final T deserObj = (T) PCEPObjectFactory.parseObjects(serBytes).get(0);
+
+               assertEquals(object, deserObj);
+       }
+
+       /*
+        * tests without the need of binary files
+        */
+       @Test
+       public void testBranchNodeObjects() throws PCEPDocumentedException, PCEPDeserializerException {
+               final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>();
+               eroSubobjects.add(new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(new byte[] {
+                               (byte) 192, (byte) 168, 1, 8 }), 16), false));
+               eroSubobjects.add(new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(new byte[] {
+                               (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168, 2, 1,
+                               (byte) 192, (byte) 168, 2, 1 }), 64), false));
+
+               serDeserTestWithoutBin(new PCEPBranchNodeListObject(eroSubobjects, true, false));
+               serDeserTestWithoutBin(new PCEPNonBranchNodeListObject(eroSubobjects, true, false));
+
+       }
+
+       @Test
+       public void testSERObjects() throws PCEPDocumentedException, PCEPDeserializerException {
+               final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>();
+               eroSubobjects.add(new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(new byte[] {
+                               (byte) 192, (byte) 168, 1, 8 }), 16), false));
+               eroSubobjects.add(new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(new byte[] {
+                               (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168, 2, 1,
+                               (byte) 192, (byte) 168, 2, 1 }), 64), false));
+
+               serDeserTestWithoutBin(new PCEPSecondaryExplicitRouteObject(eroSubobjects, true, false));
+       }
+
+       @Test
+       public void testSRRObject() throws PCEPDocumentedException, PCEPDeserializerException {
+               final List<ReportedRouteSubobject> rroSubobjects = new ArrayList<ReportedRouteSubobject>();
+               rroSubobjects.add(new RROIPAddressSubobject<IPv4Prefix>(new IPv4Prefix(this.ipv4addr, 16), true,
+                               false));
+               rroSubobjects.add(new RROIPAddressSubobject<IPv6Prefix>(new IPv6Prefix(this.ipv6addr, 64), false,
+                               true));
+
+               serDeserTestWithoutBin(new PCEPSecondaryRecordRouteObject(rroSubobjects, true, false));
+       }
+
+       @Test
+       public void testP2MPEndpointsObjects() throws PCEPDeserializerException, PCEPDocumentedException {
+               serDeserTestWithoutBin(new PCEPP2MPEndPointsObject<IPv4Address>(2, this.ipv4addr, Arrays.asList(
+                               this.ipv4addr, this.ipv4addr, this.ipv4addr), true, false));
+               serDeserTestWithoutBin(new PCEPP2MPEndPointsObject<IPv4Address>(1, this.ipv4addr,
+                               Arrays.asList(this.ipv4addr), true, false));
+               serDeserTestWithoutBin(new PCEPP2MPEndPointsObject<IPv6Address>(2, this.ipv6addr, Arrays.asList(
+                               this.ipv6addr, this.ipv6addr, this.ipv6addr), true, false));
+               serDeserTestWithoutBin(new PCEPP2MPEndPointsObject<IPv6Address>(1, this.ipv6addr,
+                               Arrays.asList(this.ipv6addr), true, false));
+       }
+
+       @Test
+       public void testUnreachedDestinationObjects() throws PCEPDeserializerException, PCEPDocumentedException {
+               serDeserTestWithoutBin(new PCEPUnreachedDestinationObject<IPv4Address>(Arrays.asList(this.ipv4addr,
+                               this.ipv4addr, this.ipv4addr), true, false));
+               serDeserTestWithoutBin(new PCEPUnreachedDestinationObject<IPv4Address>(Arrays.asList(this.ipv4addr),
+                               true, false));
+               serDeserTestWithoutBin(new PCEPUnreachedDestinationObject<IPv6Address>(Arrays.asList(this.ipv6addr,
+                               this.ipv6addr, this.ipv6addr), true, false));
+               serDeserTestWithoutBin(new PCEPUnreachedDestinationObject<IPv6Address>(Arrays.asList(this.ipv6addr),
+                               true, false));
+       }
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPSubobjectParserTest.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPSubobjectParserTest.java
new file mode 100644 (file)
index 0000000..7bceaa3
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.impl.subobject.EROAsNumberSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROIPv4PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROIPv6PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROUnnumberedInterfaceSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROExplicitExclusionRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType1Subobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType2Subobject;
+import org.opendaylight.protocol.pcep.subobject.EROType1LabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROAttributesSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType1Subobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType2Subobject;
+import org.opendaylight.protocol.pcep.subobject.RROType1LabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSubobjectAttribute;
+import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
+
+/**
+ * Tests for subobjects
+ */
+public class PCEPSubobjectParserTest {
+    final byte[] ipv6bytes1 = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+           (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+    final byte[] ipv6bytes2 = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9A, (byte) 0xBC, (byte) 0xDE, (byte) 0x12, (byte) 0x34,
+           (byte) 0x54, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+
+    final byte[] ipv4bytes1 = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+    final byte[] ipv4bytes2 = { (byte) 0x12, (byte) 0x34, (byte) 0x50, (byte) 0x00 };
+
+    @Test
+    public void testSerDeser() throws PCEPDeserializerException, IOException {
+       final byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/PackOfSubobjects.bin");
+       final List<ExplicitRouteSubobject> objsToTest = PCEPEROSubobjectParser.parse(bytesFromFile);
+
+       assertEquals(8, objsToTest.size());
+
+       assertEquals(objsToTest.get(0), new EROAsNumberSubobject(new ASNumber(0xFFFFL), true));
+       assertEquals(objsToTest.get(1), new EROAsNumberSubobject(new ASNumber(0x0010L), false));
+       assertEquals(objsToTest.get(2),
+               new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(this.ipv4bytes1), 0x20),
+                       true));
+
+       assertEquals(objsToTest.get(3),
+               new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(this.ipv4bytes2), 0x15),
+                       false));
+       assertEquals(objsToTest.get(4),
+               new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(this.ipv6bytes1), 0x80),
+                       true));
+
+       assertEquals(objsToTest.get(5),
+               new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(this.ipv6bytes2), 0x16),
+                       false));
+       final byte[] addr1 = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+       assertEquals(objsToTest.get(6), new EROUnnumberedInterfaceSubobject(new IPv4Address(addr1),
+               new UnnumberedInterfaceIdentifier(0xFFFFFFFFL), true));
+
+       final byte[] addr2 = { (byte) 0x01, (byte) 0x24, (byte) 0x56, (byte) 0x78 };
+       assertEquals(objsToTest.get(7), new EROUnnumberedInterfaceSubobject(new IPv4Address(addr2),
+               new UnnumberedInterfaceIdentifier(0x9ABCDEF0L), false));
+
+       assertArrayEquals(bytesFromFile, PCEPEROSubobjectParser.put(objsToTest));
+
+    }
+
+    @Test
+    public void testEROSubojectsSerDeserWithoutBin() throws PCEPDeserializerException {
+       final List<ExplicitRouteSubobject> objsToTest = new ArrayList<ExplicitRouteSubobject>();
+       objsToTest.add(new EROType1LabelSubobject(0xFFFF51F2L, true, false));
+       objsToTest.add(new EROType1LabelSubobject(0x12345648L, false, true));
+       objsToTest.add(new EROGeneralizedLabelSubobject(new byte[] { (byte) 0x12, (byte) 0x00, (byte) 0x25, (byte) 0xFF }, true, true));
+       objsToTest.add(new EROWavebandSwitchingLabelSubobject(0x12345678L, 0x87654321L, 0xFFFFFFFFL, false, false));
+       objsToTest.add(new EROProtectionType1Subobject(true, (byte) 0x05, true));
+       objsToTest.add(new EROProtectionType2Subobject(true, false, true, true, (byte) 0x06, (byte) 0x3f, true, false, (byte) 0x00, false));
+       objsToTest.add(new EROPathKeyWith32PCEIDSubobject(0x1235, new byte[] { (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1 }, true));
+       objsToTest.add(new EROPathKeyWith128PCEIDSubobject(0x5432, new byte[] { (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55,
+               (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1 }, true));
+       objsToTest.add(new EROExplicitExclusionRouteSubobject(Arrays.asList((ExcludeRouteSubobject) new XROAsNumberSubobject(new ASNumber(2588), true))));
+
+       assertEquals(objsToTest, PCEPEROSubobjectParser.parse(PCEPEROSubobjectParser.put(objsToTest)));
+    }
+
+    @Test
+    public void testRROSubojectsSerDeserWithoutBin() throws PCEPDeserializerException {
+       final List<ReportedRouteSubobject> objsToTest = new ArrayList<ReportedRouteSubobject>();
+       objsToTest.add(new RROIPAddressSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(this.ipv6bytes2),
+               0x16), true, false));
+       objsToTest.add(new RROIPAddressSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(this.ipv4bytes1),
+               0x16), true, false));
+       objsToTest.add(new RROType1LabelSubobject(0xFFFF51F2L, true));
+       objsToTest.add(new RROType1LabelSubobject(0x12345648L, false));
+       objsToTest.add(new RROGeneralizedLabelSubobject(new byte[] { (byte) 0x12, (byte) 0x00, (byte) 0x25, (byte) 0xFF }, true));
+       objsToTest.add(new RROWavebandSwitchingLabelSubobject(0x12345678L, 0x87654321L, 0xFFFFFFFFL, false));
+       objsToTest.add(new RROProtectionType1Subobject(true, (byte) 0x05));
+       objsToTest.add(new RROProtectionType2Subobject(true, false, true, true, (byte) 0x06, (byte) 0x3f, true, false, (byte) 0x00));
+       objsToTest.add(new RROPathKeyWith32PCEIDSubobject(0x1235, new byte[] { (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1 }));
+       objsToTest.add(new RROPathKeyWith128PCEIDSubobject(0x5432, new byte[] { (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55,
+               (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1 }));
+       objsToTest.add(new RROAttributesSubobject(new byte[] { (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF,
+               (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1 }));
+
+       assertEquals(objsToTest, PCEPRROSubobjectParser.parse(PCEPRROSubobjectParser.put(objsToTest)));
+    }
+
+    @Test
+    public void testXROSubojectsSerDeserWithoutBin() throws PCEPDeserializerException {
+       final List<ExcludeRouteSubobject> objsToTest = new ArrayList<ExcludeRouteSubobject>();
+       objsToTest.add(new XROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(this.ipv6bytes2),
+               0x16), true, XROSubobjectAttribute.INTERFACE));
+       objsToTest.add(new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(this.ipv4bytes1),
+               0x16), false, XROSubobjectAttribute.INTERFACE));
+       objsToTest.add(new XROAsNumberSubobject(new ASNumber(0x1234), true));
+       objsToTest.add(new XROUnnumberedInterfaceSubobject(new IPv4Address(this.ipv4bytes1),
+               new UnnumberedInterfaceIdentifier(0xFFFFFFFFL), true, XROSubobjectAttribute.SRLG));
+       objsToTest.add(new XROSRLGSubobject(new SharedRiskLinkGroup(0x12345678L), false));
+
+       assertEquals(objsToTest, PCEPXROSubobjectParser.parse(PCEPXROSubobjectParser.put(objsToTest)));
+    }
+
+    @Test
+    public void testDifferentLengthExceptions() {
+       final byte[] bytes = { (byte) 0x00 }; // not empty but not enought data
+                                             // for parsing subobjects
+
+       try {
+           EROAsNumberSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final PCEPDeserializerException e) {
+       }
+
+       try {
+           EROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final PCEPDeserializerException e) {
+       }
+
+       try {
+           EROIPv4PrefixSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final PCEPDeserializerException e) {
+       }
+
+       try {
+           EROIPv6PrefixSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final PCEPDeserializerException e) {
+       }
+    }
+
+    @Test
+    public void testNullExceptions() throws PCEPDeserializerException {
+       final byte[] bytes = null; // not empty but not enought data for parsing
+                                  // subobjects
+
+       try {
+           EROAsNumberSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           EROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           EROIPv4PrefixSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           EROIPv6PrefixSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+    }
+
+    @Test
+    public void testUnknownInstanceExceptions() {
+
+       final ExplicitRouteSubobject instance = new ExplicitRouteSubobject() {
+       };
+
+       try {
+           EROAsNumberSubobjectParser.put(instance);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           EROUnnumberedInterfaceSubobjectParser.put(instance);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           EROIPv4PrefixSubobjectParser.put(instance);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           final byte[] ipv6addr = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+                   (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+           EROIPv4PrefixSubobjectParser.put(new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(ipv6addr), 1), false));
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           EROIPv6PrefixSubobjectParser.put(instance);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           final byte[] ipv4addr = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+           EROIPv6PrefixSubobjectParser.put(new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(ipv4addr), 1), false));
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+    }
+
+    @Test
+    public void testEmptyExceptions() throws PCEPDeserializerException {
+       final byte[] bytes = {}; // not empty but not enought data for parsing
+                                // subobjects
+
+       try {
+           EROAsNumberSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           EROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           EROIPv4PrefixSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           EROIPv6PrefixSubobjectParser.parse(bytes, true);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+    }
+
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPTlvParserTest.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPTlvParserTest.java
new file mode 100644 (file)
index 0000000..20347cd
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.IPv4ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.IPv6ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+import org.opendaylight.protocol.pcep.impl.tlv.LSPIdentifierIPv4TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.LSPIdentifierIPv6TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.OFListTlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.PCEStatefulCapabilityTlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.RSVPErrorSpecIPv4TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.RSVPErrorSpecIPv6TlvParser;
+import org.opendaylight.protocol.pcep.tlv.IPv4LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.IPv6LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPSymbolicNameTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPUpdateErrorTlv;
+import org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import org.opendaylight.protocol.pcep.tlv.OFListTlv;
+import org.opendaylight.protocol.pcep.tlv.OrderTlv;
+import org.opendaylight.protocol.pcep.tlv.OverloadedDurationTlv;
+import org.opendaylight.protocol.pcep.tlv.P2MPCapabilityTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+import org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv;
+import org.opendaylight.protocol.pcep.tlv.ReqMissingTlv;
+
+/**
+ * Tests of PCEPTlvParser
+ */
+public class PCEPTlvParserTest {
+
+    @Test
+    public void testDeserialization() throws PCEPDeserializerException, IOException {
+       final byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/PackOfTlvs.bin");
+       final List<PCEPTlv> tlvsToTest = PCEPTlvParser.parse(bytesFromFile);
+
+       assertEquals(17, tlvsToTest.size());
+       assertEquals(tlvsToTest.get(0), new PCEStatefulCapabilityTlv(false, false, true));
+       assertEquals(tlvsToTest.get(1), new LSPStateDBVersionTlv(0xFF00FFAAB2F5F2CFL));
+       assertEquals(tlvsToTest.get(2), new PCEStatefulCapabilityTlv(false, true, true));
+       assertEquals(tlvsToTest.get(3), new LSPStateDBVersionTlv(0xFFFFFFFFFFFFFFFFL));
+       assertEquals(tlvsToTest.get(4), new NoPathVectorTlv(true, true, true, false, true, true));
+       assertEquals(tlvsToTest.get(5), new OverloadedDurationTlv(0x7FFFFFFF));
+       assertEquals(tlvsToTest.get(6), new LSPSymbolicNameTlv(new LSPSymbolicName(new String("Med test of symbolic name").getBytes())));
+       final byte[] errorCode = { (byte) 0x25, (byte) 0x68, (byte) 0x95, (byte) 0x03 };
+       assertEquals(tlvsToTest.get(7), new LSPUpdateErrorTlv(errorCode));
+       final byte[] ipv4Address = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78 };
+       final byte[] tunnelId1 = { (byte) 0x12, (byte) 0x34 };
+       final byte[] extendedTunnelID1 = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78 };
+       final byte[] lspId1 = { (byte) 0xFF, (byte) 0xFF };
+       assertEquals(tlvsToTest.get(8), new IPv4LSPIdentifiersTlv(new IPv4Address(ipv4Address),
+               new LSPIdentifier(lspId1), new TunnelIdentifier(tunnelId1), new IPv4ExtendedTunnelIdentifier(new IPv4Address(extendedTunnelID1))));
+       final byte[] ipv6Address = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9A, (byte) 0xBC, (byte) 0xDE, (byte) 0xF0, (byte) 0x12,
+               (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9A, (byte) 0xBC, (byte) 0xDE, (byte) 0xF0 };
+       final byte[] tunnelId2 = { (byte) 0xFF, (byte) 0xFF };
+       final byte[] extendedTunnelID2 = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x01,
+               (byte) 0x23, (byte) 0x45, (byte) 0x67, (byte) 0x01, (byte) 0x23, (byte) 0x45, (byte) 0x67 };
+       final byte[] lspId2 = { (byte) 0x12, (byte) 0x34 };
+       assertEquals(tlvsToTest.get(9), new IPv6LSPIdentifiersTlv(new IPv6Address(ipv6Address),
+               new LSPIdentifier(lspId2), new TunnelIdentifier(tunnelId2), new IPv6ExtendedTunnelIdentifier(new IPv6Address(extendedTunnelID2))));
+       assertEquals(tlvsToTest.get(10), new RSVPErrorSpecTlv<IPv4Address>(new IPv4Address(ipv4Address), false, true, 0x92, 0x1602));
+       assertEquals(tlvsToTest.get(11), new RSVPErrorSpecTlv<IPv6Address>(new IPv6Address(ipv6Address), true, false, 0xD5, 0xC5D9));
+       assertEquals(tlvsToTest.get(12), new ReqMissingTlv(0xF7823517L));
+       final byte[] valueBytes = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+       assertEquals(tlvsToTest.get(13), new NodeIdentifierTlv(valueBytes));
+       assertEquals(tlvsToTest.get(14), new OrderTlv(0xFFFFFFFFL, 0x00000001L));
+       assertEquals(tlvsToTest.get(15), new OFListTlv(new ArrayList<PCEPOFCodes>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(PCEPOFCodes.MCC);
+               this.add(PCEPOFCodes.MCP);
+               this.add(PCEPOFCodes.MLL);
+           }
+       }));
+       assertEquals(tlvsToTest.get(16), new P2MPCapabilityTlv(2));
+
+       assertArrayEquals(bytesFromFile, PCEPTlvParser.put(tlvsToTest));
+    }
+
+    @Test
+    public void testDifferentLengthExceptions() {
+       final byte[] bytes = { (byte) 0x00 }; // not empty but not enought data
+                                             // for parsing subobjects
+
+       try {
+           LSPIdentifierIPv4TlvParser.parse(bytes);
+           fail("");
+       } catch (final PCEPDeserializerException e) {
+       }
+
+       try {
+           LSPIdentifierIPv6TlvParser.parse(bytes);
+           fail("");
+       } catch (final PCEPDeserializerException e) {
+       }
+
+       try {
+           PCEStatefulCapabilityTlvParser.deserializeValueField(bytes);
+           fail("");
+       } catch (final PCEPDeserializerException e) {
+       }
+
+       try {
+           RSVPErrorSpecIPv4TlvParser.parse(bytes);
+           fail("");
+       } catch (final PCEPDeserializerException e) {
+       }
+
+       try {
+           RSVPErrorSpecIPv6TlvParser.parse(bytes);
+           fail("");
+       } catch (final PCEPDeserializerException e) {
+       }
+
+       try {
+           OFListTlvParser.parse(bytes);
+           fail("");
+       } catch (final PCEPDeserializerException e) {
+       }
+    }
+
+    @Test
+    public void testUnknownInstanceExceptions() {
+       try {
+           LSPIdentifierIPv4TlvParser.put(null);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           LSPIdentifierIPv6TlvParser.put(null);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           PCEStatefulCapabilityTlvParser.serializeValueField(null);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           RSVPErrorSpecIPv4TlvParser.put(null);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           RSVPErrorSpecIPv6TlvParser.put(null);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           OFListTlvParser.put(null);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+    }
+
+    @Test
+    public void testEmptyExceptions() throws PCEPDeserializerException {
+       final byte[] bytes = {}; // empty
+
+       try {
+           LSPIdentifierIPv4TlvParser.parse(bytes);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           LSPIdentifierIPv6TlvParser.parse(bytes);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           PCEStatefulCapabilityTlvParser.deserializeValueField(bytes);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           RSVPErrorSpecIPv4TlvParser.parse(bytes);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           RSVPErrorSpecIPv6TlvParser.parse(bytes);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+
+       try {
+           OFListTlvParser.parse(bytes);
+           fail("");
+       } catch (final IllegalArgumentException e) {
+       }
+    }
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPValidatorTest.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPValidatorTest.java
new file mode 100644 (file)
index 0000000..7f017f0
--- /dev/null
@@ -0,0 +1,821 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageFactory.PCEPMessageType;
+import org.opendaylight.protocol.pcep.impl.message.PCEPRawMessage;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCCreateMessage;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
+import org.opendaylight.protocol.pcep.message.PCEPXRAddTunnelMessage;
+import org.opendaylight.protocol.pcep.message.PCEPXRDeleteTunnelMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositeInstantiationObject;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.CompositePathObject;
+import org.opendaylight.protocol.pcep.object.CompositeReplySvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestSvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+import org.opendaylight.protocol.pcep.object.CompositeRptPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPSymbolicNameTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+
+public class PCEPValidatorTest {
+
+    private static final PCEPLspaObject lspa = new PCEPLspaObject(0L, 0L, 0L, (short) 0, (short) 0, false, false, false, false);
+
+    private final List<ExplicitRouteSubobject> eroSubobjects = asList(
+           new EROAsNumberSubobject(new ASNumber(0xFFFFL), false),
+           new EROUnnumberedInterfaceSubobject(new IPv4Address(
+                   new byte[] { (byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33 }), new UnnumberedInterfaceIdentifier(0x00FF00FF), false));
+
+    private final List<ReportedRouteSubobject> rroSubobjects = asList((ReportedRouteSubobject) new RROUnnumberedInterfaceSubobject(new IPv4Address(new byte[] { (byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33 }),
+           new UnnumberedInterfaceIdentifier(0x00FF00FF)));
+
+    private final List<Long> requestIds = asList(0x000001L);
+
+    private final IPv4Address ip4addr = new IPv4Address(new byte[] { (byte) 0xFF, 0x00, 0x00, 0x01 });
+
+    private final PCEPSvecObject svecObj = new PCEPSvecObject(true, true, true, false, false, PCEPValidatorTest.this.requestIds, true);
+
+    private final PCEPRequestParameterObject requestParameter = new PCEPRequestParameterObject(true, false, false, false, false, false, false, false,
+           (short) 3, 1, true, false);
+
+    // private final PCEPEndPointsObject<IPv4Address> endPoints = new
+    // PCEPEndPointsObject<IPv4Address>(this.ip4addr, this.ip4addr);
+
+    private final PCEPEndPointsObject<IPv4Address> endPoints = new PCEPEndPointsObject<IPv4Address>(this.ip4addr, this.ip4addr);
+
+    private final PCEPMessageFactory msgFactory = new PCEPMessageFactory();
+
+    // private final PCEPClassTypeObject classType = new
+    // PCEPClassTypeObject((short) 7);
+    // private final PCEPClassTypeObjectProvider classTypeProvider = new
+    // PCEPClassTypeObjectProvider((short) 7, true);
+
+    private static List<PCEPMessage> deserMsg(final String srcFile) throws IOException, DeserializerException, DocumentedException, PCEPDeserializerException {
+               final byte[] bytesFromFile = ByteArray.fileToBytes(srcFile);
+               final PCEPRawMessage rawMessage = (PCEPRawMessage) new PCEPMessageFactory().parse(ByteArray.cutBytes(bytesFromFile, PCEPMessageHeader.COMMON_HEADER_LENGTH),
+                       new PCEPMessageHeader().fromBytes(Arrays.copyOf(bytesFromFile, PCEPMessageHeader.COMMON_HEADER_LENGTH)));
+
+               return PCEPMessageValidator.getValidator(rawMessage.getMsgType()).validate(rawMessage.getAllObjects());
+    }
+
+    @Test
+    public void testOpenMessageValidationFromBin() throws IOException, DeserializerException, DocumentedException, PCEPDeserializerException {
+       assertEquals(
+               deserMsg("src/test/resources/PCEPOpenMessage1.bin"),
+               asList(new PCEPOpenMessage(new PCEPOpenObject(30, 120, 1, asList(new PCEStatefulCapabilityTlv(false, true, true), new LSPStateDBVersionTlv(
+                       0x80))))));
+
+       assertEquals(deserMsg("src/test/resources/Open.1.bin"), asList(new PCEPOpenMessage(new PCEPOpenObject(1, 4, 1))));
+
+       assertEquals(
+               deserMsg("src/test/resources/Open.3.bin"),
+               asList(new PCEPOpenMessage(new PCEPOpenObject(1, 4, 1, asList(new PCEStatefulCapabilityTlv(false, true, true), new LSPStateDBVersionTlv(53))))));
+    }
+
+    @Test
+    public void testKeepAliveMessageValidationFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+       assertEquals(deserMsg("src/test/resources/PCEPKeepAliveMessage1.bin"), asList(new PCEPKeepAliveMessage()));
+       assertEquals(deserMsg("src/test/resources/Keepalive.1.bin"), asList(new PCEPKeepAliveMessage()));
+    }
+
+    @Test
+    public void testCloseMsg() throws PCEPDeserializerException, IOException, PCEPDocumentedException, DeserializerException, DocumentedException {
+       assertEquals(deserMsg("src/test/resources/PCEPCloseMessage1.bin"), asList(new PCEPCloseMessage(new PCEPCloseObject(Reason.TOO_MANY_UNKNOWN_MSG))));
+       assertEquals(deserMsg("src/test/resources/Close.1.bin"), asList(new PCEPCloseMessage(new PCEPCloseObject(Reason.UNKNOWN))));
+    }
+
+    @Test
+    public void testRequestMessageValidationFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+       List<CompositeRequestObject> requests = new ArrayList<CompositeRequestObject>();
+       final byte[] ipAdress = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+       requests.add(new CompositeRequestObject(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 5, 0xDEADBEEFL,
+               true, false), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress), new IPv4Address(ipAdress))));
+       PCEPRequestMessage specMessage = new PCEPRequestMessage(requests);
+       List<PCEPMessage> deserMsgs = deserMsg("src/test/resources/PCEPRequestMessage1.bin");
+       final List<PCEPMessage> specMessages = new ArrayList<PCEPMessage>();
+       specMessages.add(specMessage);
+
+       assertEquals(deserMsgs, specMessages);
+
+       requests = new ArrayList<CompositeRequestObject>();
+       final byte[] ipAdress2 = { (byte) 0x7F, (byte) 0x00, (byte) 0x00, (byte) 0x01 };
+       requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress2))));
+       specMessage = new PCEPRequestMessage(requests);
+       deserMsgs = deserMsg("src/test/resources/PCReq.1.bin");
+       specMessages.clear();
+       specMessages.add(specMessage);
+       assertEquals(deserMsgs, specMessages);
+
+       requests = new ArrayList<CompositeRequestObject>();
+       requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress2)), null, null, null, null,
+               null, null, null, null, new PCEPLoadBalancingObject(3, new Bandwidth(1024.75f), false)));
+       specMessage = new PCEPRequestMessage(requests);
+       deserMsgs = deserMsg("src/test/resources/PCReq.2.bin");
+       specMessages.clear();
+       specMessages.add(specMessage);
+       assertEquals(deserMsgs, specMessages);
+
+       requests = new ArrayList<CompositeRequestObject>();
+       requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress2)), null, new PCEPLspObject(1,
+               false, false, true, false), PCEPValidatorTest.lspa, new PCEPRequestedPathBandwidthObject(new Bandwidth(1000), false, false),
+               new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new IGPMetric(53L), false, false));
+                   }
+               }, new PCEPReportedRouteObject(this.rroSubobjects, false), new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false),
+               new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new PCEPLoadBalancingObject(5, new Bandwidth(3f), false)));
+
+       List<CompositeRequestSvecObject> svecList = new ArrayList<CompositeRequestSvecObject>();
+       svecList.add(new CompositeRequestSvecObject(new PCEPSvecObject(true, false, false, false, false, this.requestIds, false)));
+
+       specMessage = new PCEPRequestMessage(svecList, requests);
+       deserMsgs = deserMsg("src/test/resources/PCReq.3.bin");
+       specMessages.clear();
+       specMessages.add(specMessage);
+       assertEquals(deserMsgs, specMessages);
+
+       specMessages.clear();
+       requests = new ArrayList<CompositeRequestObject>();
+       requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress2)), null, null, null, null,
+               null, null, null, null, null));
+       specMessages.add(new PCEPRequestMessage(requests));
+
+       final byte[] ipAdress3 = { (byte) 0x7F, (byte) 0x00, (byte) 0x30, (byte) 0x01 };
+       requests = new ArrayList<CompositeRequestObject>();
+       requests.add(new CompositeRequestObject(new PCEPRequestParameterObject(false, false, false, false, false, false, false, false, (short) 4, 1, true,
+               false), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress3), new IPv4Address(ipAdress2)), null, null, null, null, null, null, null, null, null));
+       specMessages.add(new PCEPRequestMessage(requests));
+
+       final byte[] ipAdress4 = { (byte) 0x7F, (byte) 0x30, (byte) 0x00, (byte) 0x01 };
+       requests = new ArrayList<CompositeRequestObject>();
+       requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress4)), null, null, null, null,
+               null, null, null, null, null));
+       specMessages.add(new PCEPRequestMessage(requests));
+
+       final byte[] ipAdress5 = { (byte) 0x7F, (byte) 0xd0, (byte) 0x00, (byte) 0x01 };
+       requests = new ArrayList<CompositeRequestObject>();
+       requests.add(new CompositeRequestObject(
+               new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 1, true, false),
+               new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress5), new IPv4Address(ipAdress5)), null, null, null, null, null, null, null, null, null));
+
+       specMessages.add(new PCEPRequestMessage(requests));
+       deserMsgs = deserMsg("src/test/resources/PCReq.4.bin");
+       assertEquals(deserMsgs, specMessages);
+
+       specMessages.clear();
+       svecList = new ArrayList<CompositeRequestSvecObject>();
+       svecList.add(new CompositeRequestSvecObject(new PCEPSvecObject(true, false, false, false, false, this.requestIds, false)));
+       svecList.add(new CompositeRequestSvecObject(new PCEPSvecObject(false, true, true, false, false, this.requestIds, false),
+               new PCEPObjectiveFunctionObject(PCEPOFCodes.MCC, true, false), new PCEPGlobalConstraintsObject((short) 0x55, (short) 1, (short) 100,
+                       (short) 0x26, true, false), new PCEPExcludeRouteObject(new ArrayList<ExcludeRouteSubobject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new XROAsNumberSubobject(new ASNumber(0x12), true));
+                   }
+               }, true, true, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new TEMetric(123456L), true, false));
+                   }
+               }));
+
+       requests = new ArrayList<CompositeRequestObject>();
+       requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress2)), null, null,
+               PCEPValidatorTest.lspa, new PCEPRequestedPathBandwidthObject(new Bandwidth(1000), false, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new IGPMetric(53L), false, false));
+                       this.add(new PCEPMetricObject(true, true, new IGPMetric(5335L), false, false));
+                       this.add(new PCEPMetricObject(true, true, new IGPMetric(128256), false, false));
+                   }
+               }, new PCEPReportedRouteObject(this.rroSubobjects, false), new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false),
+               new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new PCEPLoadBalancingObject(5, new Bandwidth(3f), false)));
+
+       final byte[] ipAdress6 = { (byte) 0x7F, (byte) 0xF0, (byte) 0x00, (byte) 0x01 };
+       specMessages.add(new PCEPRequestMessage(svecList, requests));
+
+       requests = new ArrayList<CompositeRequestObject>();
+       requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress6), new IPv4Address(ipAdress6)), null, null,
+               PCEPValidatorTest.lspa, new PCEPRequestedPathBandwidthObject(new Bandwidth(1000), false, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new IGPMetric(53L), false, false));
+                   }
+               }, new PCEPReportedRouteObject(this.rroSubobjects, false), new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false),
+               new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new PCEPLoadBalancingObject(5, new Bandwidth(3f), false)));
+       deserMsgs = deserMsg("src/test/resources/PCReq.5.bin");
+       specMessages.add(new PCEPRequestMessage(svecList, requests));
+       assertEquals(deserMsgs, specMessages);
+
+       // FIXME: need construct with invalid processed parameter
+       // assertEquals(deserMsg("src/test/resources/PCReq.6.invalid.bin"),
+       // asList(
+       // new PCEPErrorMessage(new CompositeErrorObject(new
+       // PCEPRequestParameterObject(true, false, false, false, false, false,
+       // false, false, (short) 3,
+       // 1L, false, false), new PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))),
+       // new PCEPRequestMessage(asList(new
+       // CompositeRequestObject(this.requestParameter, new
+       // PCEPEndPointsObject<IPv4Address>(IPv4Address
+       // .getNetworkAddressFactory().getNetworkAddressForBytes(new byte[] {
+       // 127, 0, 0, 1 }), IPv4Address.getNetworkAddressFactory()
+       // .getNetworkAddressForBytes(new byte[] { 127, 0, 0, 1 })), null, null,
+       // null, null, null, null, null, null, new PCEPLoadBalancingObject(
+       // 3, new Bandwidth(1024.75), false))))));
+
+    }
+
+    @Test
+    public void testRequestMessageValidationFromRawMsg() throws PCEPDeserializerException {
+       List<PCEPObject> objs = new ArrayList<PCEPObject>();
+       List<PCEPMessage> msgs;
+       PCEPRequestParameterObject tmpRP;
+
+       // test unrecognized object in svec list
+       objs.add(this.svecObj);
+       objs.add(new UnknownObject(true, false, PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+       objs.add(new PCEPSvecObject(true, true, true, false, false, PCEPValidatorTest.this.requestIds, true));
+
+       msgs = PCEPMessageValidator.getValidator(PCEPMessageType.REQUEST).validate(objs);
+
+       assertEquals(msgs.get(0), new PCEPErrorMessage(new ArrayList<PCEPErrorObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+           }
+       }));
+
+       // test with request p flag not set and ignoracion of more than one
+       // end-points objects
+       objs = new ArrayList<PCEPObject>();
+       objs.add(this.svecObj);
+       objs.add(this.svecObj);
+       tmpRP = new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 3, 1, false, false);
+       objs.add(tmpRP);
+       objs.add(this.endPoints);
+
+       objs.add(this.requestParameter);
+       objs.add(this.endPoints);
+       objs.add(this.endPoints);
+       // FIXME:mv use object constructor with set processed flag
+       // objs.add(this.classTypeProvider);
+       // objs.add(this.requestParameter);
+       // objs.add(this.endPointsProvider);
+       // objs.add(new PCEPClassTypeObjectProvider((short) 7, false));
+
+       msgs = PCEPMessageValidator.getValidator(PCEPMessageType.REQUEST).validate(objs);
+       // FIXME:mv use object constructor with set processed flag
+       // assertEquals(msgs.get(0), new PCEPErrorMessage(new
+       // CompositeErrorObject(tmpRP, new
+       // PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))));
+       // assertEquals(
+       // msgs.get(1),
+       // new PCEPRequestMessage(asList(new
+       // CompositeRequestSvecObject(this.svecObj), new
+       // CompositeRequestSvecObject(this.svecObj)), Util
+       // .asList(new CompositeRequestObject(this.requestParameter,
+       // this.endPoints, this.classType, null, null, null, null, null, null,
+       // null,
+       // null))));
+       // assertEquals(msgs.get(2), new PCEPErrorMessage(new
+       // CompositeErrorObject(tmpRP, new
+       // PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))));
+    }
+
+    @Test
+    public void testReplyMessageValidatorFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+
+       List<PCEPReplyMessage> specMessages = new ArrayList<PCEPReplyMessage>();
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+               false, false, (short) 5, 0xDEADBEEFL, true, true)))));
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, false, false, false,
+               false, false, (short) 7, 0x12345678L, false, false)))));
+       assertEquals(deserMsg("src/test/resources/PCEPReplyMessage1.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPReplyMessage>();
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+               false, false, (short) 3, 1, false, false)))));
+       assertEquals(deserMsg("src/test/resources/PCRep.1.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPReplyMessage>();
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+               false, false, (short) 3, 1, false, false)))));
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(false, false, false, false, false, false,
+               false, false, (short) 5, 2, false, false), new PCEPNoPathObject((short) 0, false, false), null, null, null, null, null, null))));
+       assertEquals(deserMsg("src/test/resources/PCRep.2.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPReplyMessage>();
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+               false, false, (short) 3, 1, false, false), new PCEPNoPathObject((short) 1, true, false), new PCEPLspObject(1, true, true, false, true),
+               PCEPValidatorTest.lspa, new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new IGPMetric(234), false, false));
+                   }
+               }, new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new ArrayList<CompositePathObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new CompositePathObject(new PCEPExplicitRouteObject(PCEPValidatorTest.this.eroSubobjects, false), lspa,
+                               new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+                                   private static final long serialVersionUID = 1L;
+
+                                   {
+                                       this.add(new PCEPMetricObject(true, true, new IGPMetric(234L), false, false));
+                                   }
+                               }, new PCEPIncludeRouteObject(PCEPValidatorTest.this.eroSubobjects, false, false)));
+                   }
+               }))));
+       assertEquals(deserMsg("src/test/resources/PCRep.3.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPReplyMessage>();
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+               false, false, (short) 7, 1, false, false)))));
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+               false, false, (short) 1, 2, false, false)))));
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+               false, false, (short) 2, 4, false, false)))));
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(false, false, false, false, false, false,
+               false, false, (short) 3, 4, false, false)))));
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(false, false, false, false, false, false,
+               false, false, (short) 6, 5, false, false)))));
+       assertEquals(deserMsg("src/test/resources/PCRep.4.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPReplyMessage>();
+       final List<Long> requestIDs = new ArrayList<Long>();
+       requestIDs.add(0x25069045L);
+
+       final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+       metrics.add(new PCEPMetricObject(true, true, new IGPMetric(234L), true, false));
+
+       final List<CompositeReplySvecObject> svecList = new ArrayList<CompositeReplySvecObject>();
+       svecList.add(new CompositeReplySvecObject(new PCEPSvecObject(true, true, true, false, false, requestIDs, true), new PCEPObjectiveFunctionObject(
+               PCEPOFCodes.MCC, true, false), metrics));
+
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+               false, false, (short) 3, 1, false, false), new PCEPNoPathObject((short) 1, true, false), null, PCEPValidatorTest.lspa,
+               new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new IGPMetric(234), false, false));
+                   }
+               }, new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new ArrayList<CompositePathObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new CompositePathObject(new PCEPExplicitRouteObject(PCEPValidatorTest.this.eroSubobjects, false), lspa,
+                               new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+                                   private static final long serialVersionUID = 1L;
+
+                                   {
+                                       this.add(new PCEPMetricObject(true, true, new IGPMetric(234L), false, false));
+                                       this.add(new PCEPMetricObject(true, true, new IGPMetric(5355L), false, false));
+                                       this.add(new PCEPMetricObject(true, true, new IGPMetric(5353L), false, false));
+                                   }
+                               }, new PCEPIncludeRouteObject(PCEPValidatorTest.this.eroSubobjects, false, false)));
+                   }
+               })), svecList));
+       specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+               false, false, (short) 3, 1, false, false), new PCEPNoPathObject((short) 1, true, false), null, PCEPValidatorTest.lspa,
+               new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, true, new IGPMetric(234), false, false));
+                   }
+               }, new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new ArrayList<CompositePathObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new CompositePathObject(new PCEPExplicitRouteObject(PCEPValidatorTest.this.eroSubobjects, false), lspa,
+                               new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+                                   private static final long serialVersionUID = 1L;
+
+                                   {
+                                       this.add(new PCEPMetricObject(true, true, new IGPMetric(234L), false, false));
+                                   }
+                               }, new PCEPIncludeRouteObject(PCEPValidatorTest.this.eroSubobjects, false, false)));
+                       this.add(new CompositePathObject(new PCEPExplicitRouteObject(PCEPValidatorTest.this.eroSubobjects, false), lspa,
+                               new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+                                   private static final long serialVersionUID = 1L;
+
+                                   {
+                                       this.add(new PCEPMetricObject(true, true, new IGPMetric(234L), false, false));
+                                   }
+                               }, new PCEPIncludeRouteObject(PCEPValidatorTest.this.eroSubobjects, false, false)));
+                   }
+               })), svecList));
+       assertEquals(deserMsg("src/test/resources/PCRep.5.bin"), specMessages);
+    }
+
+    @Test
+    public void testUpdMessageValidatorFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+       List<PCEPMessage> specMessages = new ArrayList<PCEPMessage>();
+
+       List<CompositeUpdateRequestObject> requests = new ArrayList<CompositeUpdateRequestObject>();
+       requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true)));
+
+       specMessages.add(new PCEPUpdateRequestMessage(requests));
+       assertEquals(deserMsg("src/test/resources/PCUpd.1.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPMessage>();
+       List<CompositeUpdPathObject> paths = new ArrayList<CompositeUpdPathObject>();
+       paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa, null, null));
+       requests = new ArrayList<CompositeUpdateRequestObject>();
+       requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true), paths));
+       specMessages.add(new PCEPUpdateRequestMessage(requests));
+       assertEquals(deserMsg("src/test/resources/PCUpd.2.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPMessage>();
+       paths = new ArrayList<CompositeUpdPathObject>();
+       paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+               new PCEPRequestedPathBandwidthObject(new Bandwidth(5353), false, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                   }
+               }));
+       requests = new ArrayList<CompositeUpdateRequestObject>();
+       requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true), paths));
+       specMessages.add(new PCEPUpdateRequestMessage(requests));
+       assertEquals(deserMsg("src/test/resources/PCUpd.3.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPMessage>();
+       requests = new ArrayList<CompositeUpdateRequestObject>();
+       requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true)));
+       requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true)));
+       specMessages.add(new PCEPUpdateRequestMessage(requests));
+       assertEquals(deserMsg("src/test/resources/PCUpd.4.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPMessage>();
+       requests = new ArrayList<CompositeUpdateRequestObject>();
+       requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true)));
+       paths = new ArrayList<CompositeUpdPathObject>();
+       paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+               new PCEPRequestedPathBandwidthObject(new Bandwidth(5353), false, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                   }
+               }));
+       requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true), paths));
+       paths = new ArrayList<CompositeUpdPathObject>();
+       paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+               new PCEPRequestedPathBandwidthObject(new Bandwidth(5353), false, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                   }
+               }));
+       paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+               new PCEPRequestedPathBandwidthObject(new Bandwidth(5353), false, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                   }
+               }));
+       paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+               new PCEPRequestedPathBandwidthObject(new Bandwidth(5353), false, false), new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                   }
+               }));
+       requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true), paths));
+       specMessages.add(new PCEPUpdateRequestMessage(requests));
+       assertEquals(deserMsg("src/test/resources/PCUpd.5.bin"), specMessages);
+    }
+
+    @Test
+    public void testRptMessageValidatorFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+       List<PCEPMessage> specMessages = new ArrayList<PCEPMessage>();
+       List<CompositeStateReportObject> reports = new ArrayList<CompositeStateReportObject>();
+       reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true)));
+       specMessages.add(new PCEPReportMessage(reports));
+       assertEquals(deserMsg("src/test/resources/PCRpt.1.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPMessage>();
+       List<CompositeRptPathObject> paths = new ArrayList<CompositeRptPathObject>();
+       paths.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa, null, null, null));
+       reports = new ArrayList<CompositeStateReportObject>();
+       reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true), paths));
+       specMessages.add(new PCEPReportMessage(reports));
+       assertEquals(deserMsg("src/test/resources/PCRpt.2.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPMessage>();
+       paths = new ArrayList<CompositeRptPathObject>();
+       paths.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+               new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false), new PCEPReportedRouteObject(this.rroSubobjects, false),
+               new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                   }
+               }));
+
+       reports = new ArrayList<CompositeStateReportObject>();
+       reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true), paths));
+       specMessages.add(new PCEPReportMessage(reports));
+       //FIXME:
+       //assertEquals(deserMsg("src/test/resources/PCRpt.3.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPMessage>();
+       reports = new ArrayList<CompositeStateReportObject>();
+       reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true)));
+       reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true)));
+       reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true)));
+       specMessages.add(new PCEPReportMessage(reports));
+       assertEquals(deserMsg("src/test/resources/PCRpt.4.bin"), specMessages);
+
+       specMessages = new ArrayList<PCEPMessage>();
+       reports = new ArrayList<CompositeStateReportObject>();
+       paths = new ArrayList<CompositeRptPathObject>();
+       paths.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+               new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false), new PCEPReportedRouteObject(this.rroSubobjects, false),
+               new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                   }
+               }));
+       reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true), paths));
+       paths = new ArrayList<CompositeRptPathObject>();
+       paths.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+               new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false), new PCEPReportedRouteObject(this.rroSubobjects, false),
+               new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                   }
+               }));
+       paths.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+               new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false), new PCEPReportedRouteObject(this.rroSubobjects, false),
+               new ArrayList<PCEPMetricObject>() {
+                   private static final long serialVersionUID = 1L;
+
+                   {
+                       this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+                   }
+               }));
+       reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true), paths));
+       specMessages.add(new PCEPReportMessage(reports));
+       //FIXME
+       //assertEquals(deserMsg("src/test/resources/PCRpt.5.bin"), specMessages);
+    }
+
+    @Test
+    public void testXRDeleteTunnelMessage() throws DeserializerException, DocumentedException, PCEPDeserializerException {
+       final PCEPXRDeleteTunnelMessage dTunnel = new PCEPXRDeleteTunnelMessage(new PCEPLspObject(1, false, true, false, true));
+       final byte[] bytes = this.msgFactory.put(dTunnel);
+
+       final PCEPRawMessage rawMessage = (PCEPRawMessage) this.msgFactory.parse(ByteArray.cutBytes(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH),
+               new PCEPMessageHeader().fromBytes(Arrays.copyOf(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH)));
+
+       assertEquals(PCEPMessageValidator.getValidator(rawMessage.getMsgType()).validate(rawMessage.getAllObjects()), asList((PCEPMessage) dTunnel));
+    }
+
+    @Test
+    public void testXRAddTunnelMessage() throws DeserializerException, DocumentedException, PCEPDeserializerException {
+       final List<ExplicitRouteSubobject> subs = new ArrayList<ExplicitRouteSubobject>();
+       subs.add(new EROAsNumberSubobject(new ASNumber(10), false));
+       final PCEPXRAddTunnelMessage addTunnel = new PCEPXRAddTunnelMessage(new PCEPLspObject(1, false, false, false, false),
+               new PCEPEndPointsObject<IPv4Address>(IPv4.FAMILY.addressForString("127.0.0.2"), IPv4.FAMILY.addressForString("127.0.0.1")),
+               new PCEPExplicitRouteObject(subs, true));
+       final byte[] bytes = this.msgFactory.put(addTunnel);
+
+       final PCEPRawMessage rawMessage = (PCEPRawMessage) this.msgFactory.parse(ByteArray.cutBytes(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH),
+               new PCEPMessageHeader().fromBytes(Arrays.copyOf(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH)));
+       assertEquals(PCEPMessageValidator.getValidator(rawMessage.getMsgType()).validate(rawMessage.getAllObjects()), asList((PCEPMessage) addTunnel));
+    }
+
+    @Test
+    public void testPCCreateMessage() throws DeserializerException, DocumentedException, PCEPDeserializerException {
+       final List<CompositeInstantiationObject> insts = new ArrayList<CompositeInstantiationObject>();
+       final List<ExplicitRouteSubobject> subs = new ArrayList<ExplicitRouteSubobject>();
+       subs.add(new EROAsNumberSubobject(new ASNumber(10), false));
+       final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>();
+       final LSPSymbolicNameTlv tlv = new LSPSymbolicNameTlv(new LSPSymbolicName(new byte[] { 5, 4 }));
+       tlvs.add(tlv);
+       insts.add(new CompositeInstantiationObject(new PCEPEndPointsObject<IPv4Address>(IPv4.FAMILY.addressForString("127.0.0.2"),
+                       IPv4.FAMILY.addressForString("127.0.0.1")), PCEPValidatorTest.lspa, new PCEPExplicitRouteObject(subs, true), null, new ArrayList<PCEPMetricObject>() {
+           private static final long serialVersionUID = 1L;
+
+           {
+               this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+               this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+               this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+           }
+       }));
+       final PCCreateMessage msg = new PCCreateMessage(insts);
+
+       final byte[] bytes = this.msgFactory.put(msg);
+
+       // FIXME: need construct with invalid processed parameter
+       final PCEPRawMessage rawMessage = (PCEPRawMessage) this.msgFactory.parse(ByteArray.cutBytes(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH),
+               new PCEPMessageHeader().fromBytes(Arrays.copyOf(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH)));
+
+       assertEquals(PCEPMessageValidator.getValidator(rawMessage.getMsgType()).validate(rawMessage.getAllObjects()), asList((PCEPMessage) msg));
+    }
+
+    @Test
+    public void testNotificationValidatorFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+       List<CompositeNotifyObject> notifications = new ArrayList<CompositeNotifyObject>();
+       List<PCEPNotificationObject> notificationsList = new ArrayList<PCEPNotificationObject>();
+       notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+       notifications.add(new CompositeNotifyObject(notificationsList));
+       PCEPNotificationMessage specMessage = new PCEPNotificationMessage(notifications);
+       assertEquals(deserMsg("src/test/resources/PCNtf.1.bin"), asList((PCEPMessage) specMessage));
+
+       notifications = new ArrayList<CompositeNotifyObject>();
+       notificationsList = new ArrayList<PCEPNotificationObject>();
+       notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+       List<PCEPRequestParameterObject> requestsList = new ArrayList<PCEPRequestParameterObject>();
+       requestsList.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 3, 1, false, false));
+       notifications.add(new CompositeNotifyObject(requestsList, notificationsList));
+       specMessage = new PCEPNotificationMessage(notifications);
+       assertEquals(deserMsg("src/test/resources/PCNtf.2.bin"), asList((PCEPMessage) specMessage));
+
+       notifications = new ArrayList<CompositeNotifyObject>();
+       notificationsList = new ArrayList<PCEPNotificationObject>();
+       notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+       requestsList = new ArrayList<PCEPRequestParameterObject>();
+       requestsList.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 10, false, false));
+       notifications.add(new CompositeNotifyObject(requestsList, notificationsList));
+       specMessage = new PCEPNotificationMessage(notifications);
+       assertEquals(deserMsg("src/test/resources/PCNtf.3.bin"), asList((PCEPMessage) specMessage));
+
+       notifications = new ArrayList<CompositeNotifyObject>();
+       notificationsList = new ArrayList<PCEPNotificationObject>();
+       notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+       notificationsList.add(new PCEPNotificationObject((short) 1, (short) 2));
+       notificationsList.add(new PCEPNotificationObject((short) 2, (short) 1));
+       notificationsList.add(new PCEPNotificationObject((short) 2, (short) 2));
+       notifications.add(new CompositeNotifyObject(notificationsList));
+       specMessage = new PCEPNotificationMessage(notifications);
+       assertEquals(deserMsg("src/test/resources/PCNtf.4.bin"), asList((PCEPMessage) specMessage));
+
+       notifications = new ArrayList<CompositeNotifyObject>();
+       notificationsList = new ArrayList<PCEPNotificationObject>();
+       notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+       requestsList = new ArrayList<PCEPRequestParameterObject>();
+       requestsList.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 10, false, false));
+       notifications.add(new CompositeNotifyObject(requestsList, notificationsList));
+       notificationsList = new ArrayList<PCEPNotificationObject>();
+       notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+       notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+       requestsList = new ArrayList<PCEPRequestParameterObject>();
+       requestsList.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 10, false, false));
+       requestsList.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 10, false, false));
+       notifications.add(new CompositeNotifyObject(requestsList, notificationsList));
+       specMessage = new PCEPNotificationMessage(notifications);
+       assertEquals(deserMsg("src/test/resources/PCNtf.5.bin"), asList((PCEPMessage) specMessage));
+    }
+
+    @Test
+    public void testErrorMessageValidatoinFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+       List<PCEPErrorObject> errorsList = new ArrayList<PCEPErrorObject>();
+       errorsList.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+
+       PCEPErrorMessage specMessage = new PCEPErrorMessage(errorsList);
+       assertEquals(deserMsg("src/test/resources/PCErr.1.bin"), asList((PCEPMessage) specMessage));
+
+       List<PCEPRequestParameterObject> requests = new ArrayList<PCEPRequestParameterObject>();
+       requests.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 3, 1, false, false));
+
+       List<CompositeErrorObject> errors = new ArrayList<CompositeErrorObject>();
+       errors.add(new CompositeErrorObject(requests, errorsList));
+
+       specMessage = new PCEPErrorMessage(errors);
+       assertEquals(deserMsg("src/test/resources/PCErr.2.bin"), asList((PCEPMessage) specMessage));
+
+       specMessage = new PCEPErrorMessage(new PCEPOpenObject(0, 0, 0), errorsList, null);
+       assertEquals(deserMsg("src/test/resources/PCErr.3.bin"), asList((PCEPMessage) specMessage));
+
+       requests = new ArrayList<PCEPRequestParameterObject>();
+       requests.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 53, false, false));
+
+       errors = new ArrayList<CompositeErrorObject>();
+       errors.add(new CompositeErrorObject(requests, errorsList));
+
+       specMessage = new PCEPErrorMessage(errors);
+       assertEquals(deserMsg("src/test/resources/PCErr.3b.bin"), asList((PCEPMessage) specMessage));
+
+       errorsList = new ArrayList<PCEPErrorObject>();
+       errorsList.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+       errorsList.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+       errorsList.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+
+       specMessage = new PCEPErrorMessage(null, errorsList, null);
+       assertEquals(deserMsg("src/test/resources/PCErr.4.bin"), asList((PCEPMessage) specMessage));
+
+       requests = new ArrayList<PCEPRequestParameterObject>();
+       requests.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 53, false, false));
+
+       errorsList = new ArrayList<PCEPErrorObject>();
+       errorsList.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+
+       errors = new ArrayList<CompositeErrorObject>();
+       errors.add(new CompositeErrorObject(requests, errorsList));
+       errors.add(new CompositeErrorObject(requests, errorsList));
+
+       specMessage = new PCEPErrorMessage(errors);
+       assertEquals(deserMsg("src/test/resources/PCErr.5.bin"), asList((PCEPMessage) specMessage));
+    }
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPXROSubobjectParserTest.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPXROSubobjectParserTest.java
new file mode 100644 (file)
index 0000000..3f0c7f7
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.impl.subobject.XROAsNumberSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROIPv4PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROIPv6PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROUnnumberedInterfaceSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSubobjectAttribute;
+import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
+
+public class PCEPXROSubobjectParserTest {
+
+       @Test
+       public void testSerDeser() throws PCEPDeserializerException, IOException {
+               final byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/PackOfXROSubobjects.bin");
+               final List<ExcludeRouteSubobject> objsToTest = PCEPXROSubobjectParser.parse(bytesFromFile);
+
+               assertEquals(5, objsToTest.size());
+
+               assertEquals(
+                               objsToTest.get(0),
+                               new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(
+                                               new byte[] { (byte) 192, (byte) 168, (byte) 0, (byte) 0 }), 16), true, XROSubobjectAttribute.NODE));
+               assertEquals(
+                               objsToTest.get(1),
+                               new XROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(
+                                               new byte[] { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x90, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78,
+                                                               (byte) 0x90, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0, (byte) 0 }), 112), true,
+                                               XROSubobjectAttribute.INTERFACE));
+               assertEquals(
+                               objsToTest.get(2),
+                               new XROUnnumberedInterfaceSubobject(new IPv4Address(
+                                               new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0x20 }), new UnnumberedInterfaceIdentifier(0x1234L), false,
+                                               XROSubobjectAttribute.SRLG));
+               assertEquals(objsToTest.get(3), new XROAsNumberSubobject(new ASNumber(0x1234), false));
+               assertEquals(objsToTest.get(4), new XROSRLGSubobject(new SharedRiskLinkGroup(0x12345678L), false));
+
+               assertArrayEquals(bytesFromFile, PCEPXROSubobjectParser.put(objsToTest));
+
+       }
+
+       @Test
+       public void testDifferentLengthExceptions() {
+               final byte[] bytes = { (byte) 0x00 }; //not empty but not enought data for parsing subobjects
+
+               try {
+                       XROAsNumberSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final PCEPDeserializerException e) {
+               }
+
+               try {
+                       XROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final PCEPDeserializerException e) {
+               }
+
+               try {
+                       XROIPv4PrefixSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final PCEPDeserializerException e) {
+               }
+
+               try {
+                       XROIPv6PrefixSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final PCEPDeserializerException e) {
+               }
+       }
+
+       @Test
+       public void testNullExceptions() throws PCEPDeserializerException {
+               final byte[] bytes = null; //not empty but not enought data for parsing subobjects
+
+               try {
+                       XROAsNumberSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       XROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       XROIPv4PrefixSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       XROIPv6PrefixSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+       }
+
+       @Test
+       public void testUnknownInstanceExceptions() {
+
+               final ExcludeRouteSubobject instance = new ExcludeRouteSubobject(true) {
+               };
+
+               try {
+                       XROAsNumberSubobjectParser.put(instance);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       XROUnnumberedInterfaceSubobjectParser.put(instance);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       XROIPv4PrefixSubobjectParser.put(instance);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       final byte[] ipv6addr = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+                                       (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+                       XROIPv4PrefixSubobjectParser.put(new XROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(ipv6addr), 1), false, XROSubobjectAttribute.INTERFACE));
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       XROIPv6PrefixSubobjectParser.put(instance);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       final byte[] ipv4addr = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+                       XROIPv6PrefixSubobjectParser.put(new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(ipv4addr), 1), false, XROSubobjectAttribute.INTERFACE));
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+       }
+
+       @Test
+       public void testEmptyExceptions() throws PCEPDeserializerException {
+               final byte[] bytes = {}; //not empty but not enought data for parsing subobjects
+
+               try {
+                       XROAsNumberSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       XROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       XROIPv4PrefixSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+
+               try {
+                       XROIPv6PrefixSubobjectParser.parse(bytes, true);
+                       fail("");
+               } catch (final IllegalArgumentException e) {
+               }
+       }
+
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/ServerSessionMock.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/ServerSessionMock.java
new file mode 100644 (file)
index 0000000..7f72e07
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import org.opendaylight.protocol.pcep.PCEPCloseTermination;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.Timer;
+
+public class ServerSessionMock extends PCEPSessionImpl {
+
+       private final MockPCE client;
+
+       public ServerSessionMock(final PCEPSessionListener listener, final PCEPSessionListener client) {
+               super(new MockDispatcher(), new Timer(), new PCEPConnection() {
+                       @Override
+                       public InetSocketAddress getPeerAddress() {
+                               try {
+                                       return new InetSocketAddress(InetAddress.getByName("localhost"), 4189);
+                               } catch (final UnknownHostException e) {
+                                       e.printStackTrace();
+                               }
+                               return null;
+                       }
+
+                       @Override
+                       public PCEPSessionListener getListener() {
+                               return listener;
+                       }
+
+                       @Override
+                       public PCEPSessionPreferences getProposal() {
+                               return new PCEPSessionPreferences(new PCEPOpenObject(4, 9, 2));
+                       }
+
+                       @Override
+                       public PCEPSessionProposalChecker getProposalChecker() {
+                               return new SimpleSessionProposalChecker();
+                       }
+               }, new PCEPMessageFactory(), 5, 30);
+               this.client = (MockPCE) client;
+       }
+
+       @Override
+       public void sendMessage(final PCEPMessage msg) {
+               this.lastMessageSentAt = System.nanoTime();
+               this.client.onMessage(this, msg);
+       }
+
+       @Override
+       public void close() {
+               this.client.onSessionTerminated(this, new PCEPCloseTermination(Reason.UNKNOWN));
+       }
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/SimpleSessionListener.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/SimpleSessionListener.java
new file mode 100644 (file)
index 0000000..3f7b5a7
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Simple Session Listener that is notified about messages and changes in the session.
+ */
+public class SimpleSessionListener extends PCEPSessionListener {
+
+       public List<PCEPMessage> messages = new ArrayList<PCEPMessage>();
+
+       public boolean up = false;
+
+       private static final Logger logger = LoggerFactory.getLogger(SimpleSessionListener.class);
+
+       public SimpleSessionListener() {
+       }
+
+       @Override
+       public void onMessage(PCEPSession session, PCEPMessage message) {
+               logger.debug("Received message: " + message.getClass() + " " + message);
+               this.messages.add(message);
+       }
+
+       @Override
+       public synchronized void onSessionUp(PCEPSession session, PCEPOpenObject local,
+                       PCEPOpenObject remote) {
+               logger.debug("Session up.");
+               this.up = true;
+               this.notifyAll();
+       }
+
+       @Override
+       public void onSessionDown(PCEPSession session, PCEPCloseObject reason, Exception e) {
+               logger.debug("Session down.");
+               this.up = false;
+               //this.notifyAll();
+       }
+
+       @Override
+       public void onSessionTerminated(PCEPSession session,
+                       TerminationReason cause) {
+               logger.debug("Session terminated. Cause : " + cause.toString());
+       }
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/SimpleSessionProposalChecker.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/SimpleSessionProposalChecker.java
new file mode 100644 (file)
index 0000000..9b83753
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ *
+ */
+public class SimpleSessionProposalChecker extends PCEPSessionProposalChecker {
+
+       @Override
+       public Boolean checkSessionCharacteristics(SessionPreferences openObj) {
+               return true;
+       }
+
+       @Override
+       public PCEPSessionPreferences getNewProposal(SessionPreferences open) {
+               return new PCEPSessionPreferences(new PCEPOpenObject(1, 1, 0, null));
+       }
+
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/tlv/LSPStateDBVersionTlvParserTest.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/tlv/LSPStateDBVersionTlvParserTest.java
new file mode 100644 (file)
index 0000000..ec35bd5
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.impl.tlv;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class LSPStateDBVersionTlvParserTest {
+       @Test
+       public void testEquality() throws IOException, PCEPDeserializerException {
+               final LSPStateDBVersionTlv objToTest1a = (LSPStateDBVersionTlv) PCEPTlvParser.parse(
+                               ByteArray.fileToBytes("src/test/resources/LSPStateDBVersionTlv1.bin")).get(0);
+               final LSPStateDBVersionTlv objToTest1b = (LSPStateDBVersionTlv) PCEPTlvParser.parse(
+                               ByteArray.fileToBytes("src/test/resources/LSPStateDBVersionTlv1.bin")).get(0);
+               final LSPStateDBVersionTlv objToTest2 = (LSPStateDBVersionTlv) PCEPTlvParser.parse(
+                               ByteArray.fileToBytes("src/test/resources/LSPStateDBVersionTlv2.bin")).get(0);
+
+               assertTrue(objToTest1a.equals(objToTest1a));
+               assertFalse(objToTest1a.equals(objToTest2));
+               assertFalse(objToTest1a == objToTest1b);
+               assertTrue(objToTest1a.equals(objToTest1b));
+       }
+
+       @Test
+       public void testSerialization() throws PCEPDeserializerException, IOException {
+               final byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/LSPStateDBVersionTlv1.bin");
+
+               final LSPStateDBVersionTlv objToTest = (LSPStateDBVersionTlv) PCEPTlvParser.parse(bytesFromFile).get(0);
+               assertEquals(objToTest.getDbVersion(), 128L);
+
+               final byte[] bytesActual = PCEPTlvParser.put(objToTest);
+
+               assertArrayEquals(bytesFromFile, bytesActual);
+       }
+
+       @Test
+       public void testConstruction() throws PCEPDeserializerException, IOException {
+               final LSPStateDBVersionTlv expected = (LSPStateDBVersionTlv) PCEPTlvParser.parse(
+                               ByteArray.fileToBytes("src/test/resources/LSPStateDBVersionTlv1.bin")).get(0);
+               final LSPStateDBVersionTlv actual = new LSPStateDBVersionTlv(128L);
+
+               assertEquals(expected, actual);
+       }
+
+       @Test(expected = PCEPDeserializerException.class)
+       public void testValidityControl() throws Exception {
+               /*
+                * Should throw exception
+                */
+               PCEPTlvParser.parse(ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlvInvalid1.bin"));
+       }
+}
diff --git a/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/tlv/PCEStatefulCapabilityTlvParserTest.java b/pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/tlv/PCEStatefulCapabilityTlvParserTest.java
new file mode 100644 (file)
index 0000000..0b024f6
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.impl.tlv;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class PCEStatefulCapabilityTlvParserTest {
+    @Test
+    public void testEquality() throws IOException, PCEPDeserializerException {
+       final PCEStatefulCapabilityTlv objToTest1a = (PCEStatefulCapabilityTlv) PCEPTlvParser.parse(
+               ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlv1.bin")).get(0);
+       final PCEStatefulCapabilityTlv objToTest1b = (PCEStatefulCapabilityTlv) PCEPTlvParser.parse(
+               ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlv1.bin")).get(0);
+       final PCEStatefulCapabilityTlv objToTest2 = (PCEStatefulCapabilityTlv) PCEPTlvParser.parse(
+               ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlv2.bin")).get(0);
+
+       assertTrue(objToTest1a.equals(objToTest1a));
+       assertFalse(objToTest1a.equals(objToTest2));
+       assertFalse(objToTest1a == objToTest1b);
+       assertTrue(objToTest1a.equals(objToTest1b));
+    }
+
+    @Test
+    public void testSerialization() throws PCEPDeserializerException, IOException {
+       final byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlv1.bin");
+
+       final PCEStatefulCapabilityTlv objToTest = (PCEStatefulCapabilityTlv) PCEPTlvParser.parse(bytesFromFile).get(0);
+       assertTrue(objToTest.isUpdate());
+       assertTrue(objToTest.isVersioned());
+
+       final byte[] bytesActual = PCEPTlvParser.put(objToTest);
+
+       assertArrayEquals(bytesFromFile, bytesActual);
+    }
+
+    @Test
+    public void testConstruction() throws PCEPDeserializerException, IOException {
+       final PCEStatefulCapabilityTlv expected = (PCEStatefulCapabilityTlv) PCEPTlvParser.parse(
+               ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlv1.bin")).get(0);
+
+       final PCEStatefulCapabilityTlv actual = new PCEStatefulCapabilityTlv(false, true, true);
+
+       assertEquals(expected, actual);
+    }
+
+    @Test(expected = PCEPDeserializerException.class)
+    public void testValidityControl() throws Exception {
+       /*
+        * Should throw exception
+        */
+       PCEPTlvParser.parse(ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlvInvalid1.bin"));
+    }
+
+}
diff --git a/pcep/impl/src/test/resources/Close.1.bin b/pcep/impl/src/test/resources/Close.1.bin
new file mode 100644 (file)
index 0000000..0d69f0e
Binary files /dev/null and b/pcep/impl/src/test/resources/Close.1.bin differ
diff --git a/pcep/impl/src/test/resources/Keepalive.1.bin b/pcep/impl/src/test/resources/Keepalive.1.bin
new file mode 100644 (file)
index 0000000..dd6707b
Binary files /dev/null and b/pcep/impl/src/test/resources/Keepalive.1.bin differ
diff --git a/pcep/impl/src/test/resources/LSPStateDBVersionTlv1.bin b/pcep/impl/src/test/resources/LSPStateDBVersionTlv1.bin
new file mode 100644 (file)
index 0000000..636c636
Binary files /dev/null and b/pcep/impl/src/test/resources/LSPStateDBVersionTlv1.bin differ
diff --git a/pcep/impl/src/test/resources/LSPStateDBVersionTlv2.bin b/pcep/impl/src/test/resources/LSPStateDBVersionTlv2.bin
new file mode 100644 (file)
index 0000000..cbd64c6
Binary files /dev/null and b/pcep/impl/src/test/resources/LSPStateDBVersionTlv2.bin differ
diff --git a/pcep/impl/src/test/resources/LSPStateDBVersionTlvInvalid1.bin b/pcep/impl/src/test/resources/LSPStateDBVersionTlvInvalid1.bin
new file mode 100644 (file)
index 0000000..43c2cfe
Binary files /dev/null and b/pcep/impl/src/test/resources/LSPStateDBVersionTlvInvalid1.bin differ
diff --git a/pcep/impl/src/test/resources/NoPathObject1WithTLV.bin b/pcep/impl/src/test/resources/NoPathObject1WithTLV.bin
new file mode 100644 (file)
index 0000000..58ca456
Binary files /dev/null and b/pcep/impl/src/test/resources/NoPathObject1WithTLV.bin differ
diff --git a/pcep/impl/src/test/resources/NoPathObject2WithoutTLV.bin b/pcep/impl/src/test/resources/NoPathObject2WithoutTLV.bin
new file mode 100644 (file)
index 0000000..6f89865
Binary files /dev/null and b/pcep/impl/src/test/resources/NoPathObject2WithoutTLV.bin differ
diff --git a/pcep/impl/src/test/resources/Open.1.bin b/pcep/impl/src/test/resources/Open.1.bin
new file mode 100644 (file)
index 0000000..673860c
Binary files /dev/null and b/pcep/impl/src/test/resources/Open.1.bin differ
diff --git a/pcep/impl/src/test/resources/Open.1.pbin b/pcep/impl/src/test/resources/Open.1.pbin
new file mode 100644 (file)
index 0000000..673860c
Binary files /dev/null and b/pcep/impl/src/test/resources/Open.1.pbin differ
diff --git a/pcep/impl/src/test/resources/Open.3.bin b/pcep/impl/src/test/resources/Open.3.bin
new file mode 100644 (file)
index 0000000..74d6462
Binary files /dev/null and b/pcep/impl/src/test/resources/Open.3.bin differ
diff --git a/pcep/impl/src/test/resources/Open.invalid.bin b/pcep/impl/src/test/resources/Open.invalid.bin
new file mode 100644 (file)
index 0000000..0ce3efd
Binary files /dev/null and b/pcep/impl/src/test/resources/Open.invalid.bin differ
diff --git a/pcep/impl/src/test/resources/PCClose.1.bin b/pcep/impl/src/test/resources/PCClose.1.bin
new file mode 100644 (file)
index 0000000..0d69f0e
Binary files /dev/null and b/pcep/impl/src/test/resources/PCClose.1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPBandwidthObject1LowerBounds.bin b/pcep/impl/src/test/resources/PCEPBandwidthObject1LowerBounds.bin
new file mode 100644 (file)
index 0000000..e6a25a7
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPBandwidthObject1LowerBounds.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPBandwidthObject2UpperBounds.bin b/pcep/impl/src/test/resources/PCEPBandwidthObject2UpperBounds.bin
new file mode 100644 (file)
index 0000000..3ebf1ec
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPBandwidthObject2UpperBounds.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPCloseMessage1.bin b/pcep/impl/src/test/resources/PCEPCloseMessage1.bin
new file mode 100644 (file)
index 0000000..e7f5a7d
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPCloseMessage1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPCloseObject1.bin b/pcep/impl/src/test/resources/PCEPCloseObject1.bin
new file mode 100644 (file)
index 0000000..29dab1a
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPCloseObject1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPEndPointsObject1IPv4.bin b/pcep/impl/src/test/resources/PCEPEndPointsObject1IPv4.bin
new file mode 100644 (file)
index 0000000..addad73
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPEndPointsObject1IPv4.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPEndPointsObject2IPv6.bin b/pcep/impl/src/test/resources/PCEPEndPointsObject2IPv6.bin
new file mode 100644 (file)
index 0000000..9470b7c
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPEndPointsObject2IPv6.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPErrorObject1.bin b/pcep/impl/src/test/resources/PCEPErrorObject1.bin
new file mode 100644 (file)
index 0000000..f7507e2
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPErrorObject1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPErrorObject2Invalid.bin b/pcep/impl/src/test/resources/PCEPErrorObject2Invalid.bin
new file mode 100644 (file)
index 0000000..6da6e2d
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPErrorObject2Invalid.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPErrorObject3.bin b/pcep/impl/src/test/resources/PCEPErrorObject3.bin
new file mode 100644 (file)
index 0000000..17e7919
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPErrorObject3.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPExcludeRouteObject.1.bin b/pcep/impl/src/test/resources/PCEPExcludeRouteObject.1.bin
new file mode 100644 (file)
index 0000000..a2c2bc9
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPExcludeRouteObject.1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPExplicitRouteObject1PackOfSubobjects.bin b/pcep/impl/src/test/resources/PCEPExplicitRouteObject1PackOfSubobjects.bin
new file mode 100644 (file)
index 0000000..7613b9b
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPExplicitRouteObject1PackOfSubobjects.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPGlobalConstraintsObject.1.bin b/pcep/impl/src/test/resources/PCEPGlobalConstraintsObject.1.bin
new file mode 100644 (file)
index 0000000..831aac4
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPGlobalConstraintsObject.1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPIncludeRouteObject1PackOfSubobjects.bin b/pcep/impl/src/test/resources/PCEPIncludeRouteObject1PackOfSubobjects.bin
new file mode 100644 (file)
index 0000000..575c129
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPIncludeRouteObject1PackOfSubobjects.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPKeepAliveMessage1.bin b/pcep/impl/src/test/resources/PCEPKeepAliveMessage1.bin
new file mode 100644 (file)
index 0000000..dd6707b
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPKeepAliveMessage1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPLoadBalancingObject1.bin b/pcep/impl/src/test/resources/PCEPLoadBalancingObject1.bin
new file mode 100644 (file)
index 0000000..7070f4b
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPLoadBalancingObject1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPLspObject1NoTlvsUpperBounds.bin b/pcep/impl/src/test/resources/PCEPLspObject1NoTlvsUpperBounds.bin
new file mode 100644 (file)
index 0000000..e8bcd0b
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPLspObject1NoTlvsUpperBounds.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPLspaObject1LowerBounds.bin b/pcep/impl/src/test/resources/PCEPLspaObject1LowerBounds.bin
new file mode 100644 (file)
index 0000000..38c3d83
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPLspaObject1LowerBounds.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPLspaObject2UpperBounds.bin b/pcep/impl/src/test/resources/PCEPLspaObject2UpperBounds.bin
new file mode 100644 (file)
index 0000000..de8441e
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPLspaObject2UpperBounds.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPLspaObject3RandVals.bin b/pcep/impl/src/test/resources/PCEPLspaObject3RandVals.bin
new file mode 100644 (file)
index 0000000..4d15629
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPLspaObject3RandVals.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPMetricObject1LowerBounds.bin b/pcep/impl/src/test/resources/PCEPMetricObject1LowerBounds.bin
new file mode 100644 (file)
index 0000000..bb6c3a7
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPMetricObject1LowerBounds.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPMetricObject2UpperBounds.bin b/pcep/impl/src/test/resources/PCEPMetricObject2UpperBounds.bin
new file mode 100644 (file)
index 0000000..4b80f38
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPMetricObject2UpperBounds.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPNotificationObject1WithTlv.bin b/pcep/impl/src/test/resources/PCEPNotificationObject1WithTlv.bin
new file mode 100644 (file)
index 0000000..827a69b
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPNotificationObject1WithTlv.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPNotificationObject2WithoutTlv.bin b/pcep/impl/src/test/resources/PCEPNotificationObject2WithoutTlv.bin
new file mode 100644 (file)
index 0000000..474b6ab
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPNotificationObject2WithoutTlv.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPObject1UnknownClass.bin b/pcep/impl/src/test/resources/PCEPObject1UnknownClass.bin
new file mode 100644 (file)
index 0000000..6229831
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPObject1UnknownClass.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPObject2UnknownType.bin b/pcep/impl/src/test/resources/PCEPObject2UnknownType.bin
new file mode 100644 (file)
index 0000000..48b2564
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPObject2UnknownType.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPObjectiveFunctionObject.1.bin b/pcep/impl/src/test/resources/PCEPObjectiveFunctionObject.1.bin
new file mode 100644 (file)
index 0000000..45094a1
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPObjectiveFunctionObject.1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPOpenMessage1.bin b/pcep/impl/src/test/resources/PCEPOpenMessage1.bin
new file mode 100644 (file)
index 0000000..b1f75d0
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPOpenMessage1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPOpenObject1.bin b/pcep/impl/src/test/resources/PCEPOpenObject1.bin
new file mode 100644 (file)
index 0000000..58f380f
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPOpenObject1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPOpenObject2UpperBoundsNoTlv.bin b/pcep/impl/src/test/resources/PCEPOpenObject2UpperBoundsNoTlv.bin
new file mode 100644 (file)
index 0000000..533fbb1
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPOpenObject2UpperBoundsNoTlv.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPOpenObject3.bin b/pcep/impl/src/test/resources/PCEPOpenObject3.bin
new file mode 100644 (file)
index 0000000..82aedb8
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPOpenObject3.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPRPObject1.bin b/pcep/impl/src/test/resources/PCEPRPObject1.bin
new file mode 100644 (file)
index 0000000..1e29dc8
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPRPObject1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPRPObject2.bin b/pcep/impl/src/test/resources/PCEPRPObject2.bin
new file mode 100644 (file)
index 0000000..2b2800a
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPRPObject2.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPReplyMessage1.bin b/pcep/impl/src/test/resources/PCEPReplyMessage1.bin
new file mode 100644 (file)
index 0000000..77038b1
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPReplyMessage1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPReportedRouteObject1PackOfSubobjects.bin b/pcep/impl/src/test/resources/PCEPReportedRouteObject1PackOfSubobjects.bin
new file mode 100644 (file)
index 0000000..90a45bc
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPReportedRouteObject1PackOfSubobjects.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPRequestMessage1.bin b/pcep/impl/src/test/resources/PCEPRequestMessage1.bin
new file mode 100644 (file)
index 0000000..1d3555f
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPRequestMessage1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPSvecObject1_10ReqIDs.bin b/pcep/impl/src/test/resources/PCEPSvecObject1_10ReqIDs.bin
new file mode 100644 (file)
index 0000000..7e75b79
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPSvecObject1_10ReqIDs.bin differ
diff --git a/pcep/impl/src/test/resources/PCEPSvecObject2.bin b/pcep/impl/src/test/resources/PCEPSvecObject2.bin
new file mode 100644 (file)
index 0000000..7f21270
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEPSvecObject2.bin differ
diff --git a/pcep/impl/src/test/resources/PCEStatefulCapabilityTlv1.bin b/pcep/impl/src/test/resources/PCEStatefulCapabilityTlv1.bin
new file mode 100644 (file)
index 0000000..34bcb8e
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEStatefulCapabilityTlv1.bin differ
diff --git a/pcep/impl/src/test/resources/PCEStatefulCapabilityTlv2.bin b/pcep/impl/src/test/resources/PCEStatefulCapabilityTlv2.bin
new file mode 100644 (file)
index 0000000..c23ed7a
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEStatefulCapabilityTlv2.bin differ
diff --git a/pcep/impl/src/test/resources/PCEStatefulCapabilityTlvInvalid1.bin b/pcep/impl/src/test/resources/PCEStatefulCapabilityTlvInvalid1.bin
new file mode 100644 (file)
index 0000000..ba8e160
Binary files /dev/null and b/pcep/impl/src/test/resources/PCEStatefulCapabilityTlvInvalid1.bin differ
diff --git a/pcep/impl/src/test/resources/PCErr.1.bin b/pcep/impl/src/test/resources/PCErr.1.bin
new file mode 100644 (file)
index 0000000..505be5e
Binary files /dev/null and b/pcep/impl/src/test/resources/PCErr.1.bin differ
diff --git a/pcep/impl/src/test/resources/PCErr.2.bin b/pcep/impl/src/test/resources/PCErr.2.bin
new file mode 100644 (file)
index 0000000..334bf77
Binary files /dev/null and b/pcep/impl/src/test/resources/PCErr.2.bin differ
diff --git a/pcep/impl/src/test/resources/PCErr.3.bin b/pcep/impl/src/test/resources/PCErr.3.bin
new file mode 100644 (file)
index 0000000..9acd722
Binary files /dev/null and b/pcep/impl/src/test/resources/PCErr.3.bin differ
diff --git a/pcep/impl/src/test/resources/PCErr.3b.bin b/pcep/impl/src/test/resources/PCErr.3b.bin
new file mode 100644 (file)
index 0000000..dfa3434
Binary files /dev/null and b/pcep/impl/src/test/resources/PCErr.3b.bin differ
diff --git a/pcep/impl/src/test/resources/PCErr.4.bin b/pcep/impl/src/test/resources/PCErr.4.bin
new file mode 100644 (file)
index 0000000..3558002
Binary files /dev/null and b/pcep/impl/src/test/resources/PCErr.4.bin differ
diff --git a/pcep/impl/src/test/resources/PCErr.5.bin b/pcep/impl/src/test/resources/PCErr.5.bin
new file mode 100644 (file)
index 0000000..23a597e
Binary files /dev/null and b/pcep/impl/src/test/resources/PCErr.5.bin differ
diff --git a/pcep/impl/src/test/resources/PCErr.invalid.bin b/pcep/impl/src/test/resources/PCErr.invalid.bin
new file mode 100644 (file)
index 0000000..64177c0
Binary files /dev/null and b/pcep/impl/src/test/resources/PCErr.invalid.bin differ
diff --git a/pcep/impl/src/test/resources/PCNtf.1.bin b/pcep/impl/src/test/resources/PCNtf.1.bin
new file mode 100644 (file)
index 0000000..fb42ee1
Binary files /dev/null and b/pcep/impl/src/test/resources/PCNtf.1.bin differ
diff --git a/pcep/impl/src/test/resources/PCNtf.2.bin b/pcep/impl/src/test/resources/PCNtf.2.bin
new file mode 100644 (file)
index 0000000..1f2b169
Binary files /dev/null and b/pcep/impl/src/test/resources/PCNtf.2.bin differ
diff --git a/pcep/impl/src/test/resources/PCNtf.3.bin b/pcep/impl/src/test/resources/PCNtf.3.bin
new file mode 100644 (file)
index 0000000..38c90ea
Binary files /dev/null and b/pcep/impl/src/test/resources/PCNtf.3.bin differ
diff --git a/pcep/impl/src/test/resources/PCNtf.4.bin b/pcep/impl/src/test/resources/PCNtf.4.bin
new file mode 100644 (file)
index 0000000..d4ab600
Binary files /dev/null and b/pcep/impl/src/test/resources/PCNtf.4.bin differ
diff --git a/pcep/impl/src/test/resources/PCNtf.5.bin b/pcep/impl/src/test/resources/PCNtf.5.bin
new file mode 100644 (file)
index 0000000..166578c
Binary files /dev/null and b/pcep/impl/src/test/resources/PCNtf.5.bin differ
diff --git a/pcep/impl/src/test/resources/PCNtf.invalid.bin b/pcep/impl/src/test/resources/PCNtf.invalid.bin
new file mode 100644 (file)
index 0000000..ff6596f
Binary files /dev/null and b/pcep/impl/src/test/resources/PCNtf.invalid.bin differ
diff --git a/pcep/impl/src/test/resources/PCRep.1.bin b/pcep/impl/src/test/resources/PCRep.1.bin
new file mode 100644 (file)
index 0000000..ddec8ef
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRep.1.bin differ
diff --git a/pcep/impl/src/test/resources/PCRep.2.bin b/pcep/impl/src/test/resources/PCRep.2.bin
new file mode 100644 (file)
index 0000000..074a888
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRep.2.bin differ
diff --git a/pcep/impl/src/test/resources/PCRep.3.bin b/pcep/impl/src/test/resources/PCRep.3.bin
new file mode 100644 (file)
index 0000000..1d00682
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRep.3.bin differ
diff --git a/pcep/impl/src/test/resources/PCRep.4.bin b/pcep/impl/src/test/resources/PCRep.4.bin
new file mode 100644 (file)
index 0000000..b3a2167
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRep.4.bin differ
diff --git a/pcep/impl/src/test/resources/PCRep.5.bin b/pcep/impl/src/test/resources/PCRep.5.bin
new file mode 100644 (file)
index 0000000..3ce7845
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRep.5.bin differ
diff --git a/pcep/impl/src/test/resources/PCRep.invalid.bin b/pcep/impl/src/test/resources/PCRep.invalid.bin
new file mode 100644 (file)
index 0000000..e2b9b93
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRep.invalid.bin differ
diff --git a/pcep/impl/src/test/resources/PCReq.1.bin b/pcep/impl/src/test/resources/PCReq.1.bin
new file mode 100644 (file)
index 0000000..3ab018a
Binary files /dev/null and b/pcep/impl/src/test/resources/PCReq.1.bin differ
diff --git a/pcep/impl/src/test/resources/PCReq.2.bin b/pcep/impl/src/test/resources/PCReq.2.bin
new file mode 100644 (file)
index 0000000..ad3c448
Binary files /dev/null and b/pcep/impl/src/test/resources/PCReq.2.bin differ
diff --git a/pcep/impl/src/test/resources/PCReq.3.bin b/pcep/impl/src/test/resources/PCReq.3.bin
new file mode 100644 (file)
index 0000000..cec3f19
Binary files /dev/null and b/pcep/impl/src/test/resources/PCReq.3.bin differ
diff --git a/pcep/impl/src/test/resources/PCReq.4.bin b/pcep/impl/src/test/resources/PCReq.4.bin
new file mode 100644 (file)
index 0000000..0e5874d
Binary files /dev/null and b/pcep/impl/src/test/resources/PCReq.4.bin differ
diff --git a/pcep/impl/src/test/resources/PCReq.5.bin b/pcep/impl/src/test/resources/PCReq.5.bin
new file mode 100644 (file)
index 0000000..4c98536
Binary files /dev/null and b/pcep/impl/src/test/resources/PCReq.5.bin differ
diff --git a/pcep/impl/src/test/resources/PCReq.6.invalid.bin b/pcep/impl/src/test/resources/PCReq.6.invalid.bin
new file mode 100644 (file)
index 0000000..8154c67
Binary files /dev/null and b/pcep/impl/src/test/resources/PCReq.6.invalid.bin differ
diff --git a/pcep/impl/src/test/resources/PCReq.invalid.bin b/pcep/impl/src/test/resources/PCReq.invalid.bin
new file mode 100644 (file)
index 0000000..a989fee
Binary files /dev/null and b/pcep/impl/src/test/resources/PCReq.invalid.bin differ
diff --git a/pcep/impl/src/test/resources/PCRpt.1.bin b/pcep/impl/src/test/resources/PCRpt.1.bin
new file mode 100644 (file)
index 0000000..6d7d9b1
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRpt.1.bin differ
diff --git a/pcep/impl/src/test/resources/PCRpt.2.bin b/pcep/impl/src/test/resources/PCRpt.2.bin
new file mode 100644 (file)
index 0000000..075677c
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRpt.2.bin differ
diff --git a/pcep/impl/src/test/resources/PCRpt.3.bin b/pcep/impl/src/test/resources/PCRpt.3.bin
new file mode 100644 (file)
index 0000000..73a4056
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRpt.3.bin differ
diff --git a/pcep/impl/src/test/resources/PCRpt.4.bin b/pcep/impl/src/test/resources/PCRpt.4.bin
new file mode 100644 (file)
index 0000000..8261352
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRpt.4.bin differ
diff --git a/pcep/impl/src/test/resources/PCRpt.5.bin b/pcep/impl/src/test/resources/PCRpt.5.bin
new file mode 100644 (file)
index 0000000..78f2594
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRpt.5.bin differ
diff --git a/pcep/impl/src/test/resources/PCRpt.invalid.bin b/pcep/impl/src/test/resources/PCRpt.invalid.bin
new file mode 100644 (file)
index 0000000..2fbc3f4
Binary files /dev/null and b/pcep/impl/src/test/resources/PCRpt.invalid.bin differ
diff --git a/pcep/impl/src/test/resources/PCUpd.1.bin b/pcep/impl/src/test/resources/PCUpd.1.bin
new file mode 100644 (file)
index 0000000..9ce5b32
Binary files /dev/null and b/pcep/impl/src/test/resources/PCUpd.1.bin differ
diff --git a/pcep/impl/src/test/resources/PCUpd.2.bin b/pcep/impl/src/test/resources/PCUpd.2.bin
new file mode 100644 (file)
index 0000000..49716e3
Binary files /dev/null and b/pcep/impl/src/test/resources/PCUpd.2.bin differ
diff --git a/pcep/impl/src/test/resources/PCUpd.3.bin b/pcep/impl/src/test/resources/PCUpd.3.bin
new file mode 100644 (file)
index 0000000..37bd08c
Binary files /dev/null and b/pcep/impl/src/test/resources/PCUpd.3.bin differ
diff --git a/pcep/impl/src/test/resources/PCUpd.4.bin b/pcep/impl/src/test/resources/PCUpd.4.bin
new file mode 100644 (file)
index 0000000..f34e02b
Binary files /dev/null and b/pcep/impl/src/test/resources/PCUpd.4.bin differ
diff --git a/pcep/impl/src/test/resources/PCUpd.5.bin b/pcep/impl/src/test/resources/PCUpd.5.bin
new file mode 100644 (file)
index 0000000..4e2fdb7
Binary files /dev/null and b/pcep/impl/src/test/resources/PCUpd.5.bin differ
diff --git a/pcep/impl/src/test/resources/PCUpd.invalid.bin b/pcep/impl/src/test/resources/PCUpd.invalid.bin
new file mode 100644 (file)
index 0000000..dfc7c88
Binary files /dev/null and b/pcep/impl/src/test/resources/PCUpd.invalid.bin differ
diff --git a/pcep/impl/src/test/resources/PackOfSubobjects.bin b/pcep/impl/src/test/resources/PackOfSubobjects.bin
new file mode 100644 (file)
index 0000000..22e5562
Binary files /dev/null and b/pcep/impl/src/test/resources/PackOfSubobjects.bin differ
diff --git a/pcep/impl/src/test/resources/PackOfTlvs.bin b/pcep/impl/src/test/resources/PackOfTlvs.bin
new file mode 100644 (file)
index 0000000..98e8383
Binary files /dev/null and b/pcep/impl/src/test/resources/PackOfTlvs.bin differ
diff --git a/pcep/impl/src/test/resources/PackOfXROSubobjects.bin b/pcep/impl/src/test/resources/PackOfXROSubobjects.bin
new file mode 100644 (file)
index 0000000..8e555d0
Binary files /dev/null and b/pcep/impl/src/test/resources/PackOfXROSubobjects.bin differ
diff --git a/pcep/pom.xml b/pcep/pom.xml
new file mode 100644 (file)
index 0000000..f194e6f
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>protocol-parent</artifactId>
+               <version>0.1</version>
+       </parent>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>pcep-parent</artifactId>
+       <description>PCEP protocol parent</description>
+       <packaging>pom</packaging>
+       <version>1.0</version>
+       <name>${project.artifactId}</name>
+       
+       <modules>
+               <module>api</module>
+               <module>impl</module>
+        <module>testtool</module>
+    </modules>
+</project>
diff --git a/pcep/testtool/.gitignore b/pcep/testtool/.gitignore
new file mode 100644 (file)
index 0000000..1e07caf
--- /dev/null
@@ -0,0 +1,4 @@
+target
+.settings
+.classpath
+.project
diff --git a/pcep/testtool/AutoResponseMessagesGenerator.groovy b/pcep/testtool/AutoResponseMessagesGenerator.groovy
new file mode 100644 (file)
index 0000000..085eef2
--- /dev/null
@@ -0,0 +1,99 @@
+import java.util.Queue
+
+import org.opendaylight.protocol.pcep.PCEPMessage
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject
+import org.opendaylight.protocol.pcep.tool.MessageGeneratorService
+
+class GroovyReplyMessageGenerator implements MessageGeneratorService {
+       
+       public GroovyReplyMessageGenerator() {
+               }
+       
+       @Override
+       public Queue<PCEPMessage> generateMessages() {
+               def queue = new LinkedList<PCEPMessage>()
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+               
+                               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+               
+                               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+               
+                               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+                               
+               return queue
+       }
+}
\ No newline at end of file
diff --git a/pcep/testtool/PeriodicallySendMessagesGenerator.groovy b/pcep/testtool/PeriodicallySendMessagesGenerator.groovy
new file mode 100644 (file)
index 0000000..085eef2
--- /dev/null
@@ -0,0 +1,99 @@
+import java.util.Queue
+
+import org.opendaylight.protocol.pcep.PCEPMessage
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject
+import org.opendaylight.protocol.pcep.tool.MessageGeneratorService
+
+class GroovyReplyMessageGenerator implements MessageGeneratorService {
+       
+       public GroovyReplyMessageGenerator() {
+               }
+       
+       @Override
+       public Queue<PCEPMessage> generateMessages() {
+               def queue = new LinkedList<PCEPMessage>()
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+               
+                               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+               
+                               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+               
+                               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+                               
+               return queue
+       }
+}
\ No newline at end of file
diff --git a/pcep/testtool/SendNowMessagesGenerator.groovy b/pcep/testtool/SendNowMessagesGenerator.groovy
new file mode 100644 (file)
index 0000000..085eef2
--- /dev/null
@@ -0,0 +1,99 @@
+import java.util.Queue
+
+import org.opendaylight.protocol.pcep.PCEPMessage
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject
+import org.opendaylight.protocol.pcep.tool.MessageGeneratorService
+
+class GroovyReplyMessageGenerator implements MessageGeneratorService {
+       
+       public GroovyReplyMessageGenerator() {
+               }
+       
+       @Override
+       public Queue<PCEPMessage> generateMessages() {
+               def queue = new LinkedList<PCEPMessage>()
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+               
+                               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+               
+                               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+               
+                               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+                               
+               return queue
+       }
+}
\ No newline at end of file
diff --git a/pcep/testtool/pom.xml b/pcep/testtool/pom.xml
new file mode 100644 (file)
index 0000000..b37d8e8
--- /dev/null
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+        <groupId>org.opendaylight.protocol</groupId>
+        <artifactId>pcep-parent</artifactId>
+        <version>1.0</version>
+    </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>pcep-testtool</artifactId>
+       <description>PCEP Interop Testing Tool</description>
+       <packaging>bundle</packaging>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>pcep-api</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>concepts</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>ch.qos.logback</groupId>
+                       <artifactId>logback-classic</artifactId>
+                       <version>${logback.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>pcep-impl</artifactId>
+                       <version>1.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>pcep-impl</artifactId>
+                       <version>1.0</version>
+                       <type>test-jar</type>
+               </dependency>
+               <dependency>
+                       <groupId>org.codehaus.groovy</groupId>
+                       <artifactId>groovy-all</artifactId>
+                       <version>2.0.2</version>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.pcep.testtool
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-shade-plugin</artifactId>
+                               <version>1.7.1</version>
+                               <configuration>
+                               </configuration>
+                               <executions>
+                                       <execution>
+                                               <phase>package</phase>
+                                               <goals>
+                                                       <goal>shade</goal>
+                                               </goals>
+                                               <configuration>
+                                                       <transformers>
+                                                               <transformer
+                                                                       implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                                                       <mainClass>org.opendaylight.protocol.pcep.testtool.Main</mainClass>
+                                                               </transformer>
+                                                       </transformers>
+                                                       <shadedArtifactAttached>true</shadedArtifactAttached>
+                                                       <shadedClassifierName>executable</shadedClassifierName>
+                                               </configuration>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+</project>
diff --git a/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/Main.java b/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/Main.java
new file mode 100644 (file)
index 0000000..7bd16b0
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.testtool;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPConnectionFactory;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
+import org.opendaylight.protocol.pcep.PCEPSessionProposal;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalCheckerFactory;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
+import org.opendaylight.protocol.pcep.impl.PCEPConnectionImpl;
+import org.opendaylight.protocol.pcep.impl.PCEPDispatcherImpl;
+import org.opendaylight.protocol.pcep.impl.PCEPSessionProposalCheckerFactoryImpl;
+import org.opendaylight.protocol.pcep.impl.PCEPSessionProposalFactoryImpl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+public class Main {
+
+       public static String usage = "DESCRIPTION:\n" + "\tCreates a server with given parameters. As long as it runs, it accepts connections "
+                       + "from PCCs.\n" + "USAGE:\n" + "\t-a, --address\n" + "\t\tthe ip address to which is this server bound.\n"
+                       + "\t\tFormat: x.x.x.x:y where y is port number.\n\n" +
+
+                       "\t-d, --deadtimer\n" + "\t\tin seconds, value of the desired deadtimer\n"
+                       + "\t\tAccording to RFC5440, recommended value for deadtimer is 4 times the value\n"
+                       + "\t\tof KeepAlive timer. If it's not, a warning is printed.\n"
+                       + "\t\tIf not set, it's value will be derived from KeepAlive timer value.\n\n" +
+
+                       "\t-ka, --keepalive\n" + "\t\tin seconds, value of the desired KeepAlive timer.\n"
+                       + "\t\tIf not present, KeepAlive timer will be set to recommended value (30s).\n\n" +
+
+                       "\t--stateful\n" + "\t\tpassive stateful\n\n" +
+
+                       "\t--active\n" + "\t\tactive stateful (implies --stateful)\n\n" +
+
+                       "\t--versioned\n" + "\t\tversioned stateful (implies --stateful)\n\n" +
+
+                       "\t--instant\n"
+                       + "\t\tinstantiated stateful, <seconds> cleanup timeout (default value, if not included = 0) (implies --stateful)\n\n" +
+
+                       "\t-arm, --autoResponseMessages <path to file>\n"
+                       + "\t\t <path to file> with groovy script which implements MessageGeneratorService.\n"
+                       + "\t\t Messages are used as auto response for every message received. Purely for testing puposes! \n\n" +
+
+                       "\t-psm, --periodicallySendMessages <path to file> <period>\n"
+                       + "\t\t <path to file> with groovy script which implements MessageGeneratorService followed by <period> in seconds.\n"
+                       + "\t\t Messages which are sent periodically. Purely for testing puposes! \n\n" +
+
+                       "\t-snm, --sendNowMessage <path to file>\n"
+                       + "\t\t <path to file> with groovy script which implements MessageGeneratorService.\n"
+                       + "\t\t Messages are sent in defined states defined by programmer. Purely for testing puposes! \n\n" +
+
+                       "\t--help\n" + "\t\tdisplay this help and exits\n\n" +
+
+                       "With no parameters, this help is printed.";
+
+       public static void main(final String[] args) throws IOException {
+               if (args.length == 0 || (args.length == 1 && args[0].equalsIgnoreCase("--help"))) {
+                       System.out.println(Main.usage);
+                       return;
+               }
+
+               InetSocketAddress address = null;
+               int keepAliveValue = 30;
+               int deadTimerValue = 0;
+               boolean stateful = false;
+               boolean active = false;
+               boolean versioned = false;
+               boolean instant = false;
+               String autoResponseMessagesSrc = null;
+               String sendNowMessageSrc = null;
+               String periodicallySendMessagesSrc = null;
+               int period = 0;
+               int timeout = 0;
+
+               int i = 0;
+               while (i < args.length) {
+                       if (args[i].equalsIgnoreCase("-a") || args[i].equalsIgnoreCase("--address")) {
+                               final String[] ip = args[i + 1].split(":");
+                               address = new InetSocketAddress(InetAddress.getByName(ip[0]), Integer.valueOf(ip[1]));
+                               i++;
+                       } else if (args[i].equalsIgnoreCase("-d") || args[i].equalsIgnoreCase("--deadtimer")) {
+                               deadTimerValue = Integer.valueOf(args[i + 1]);
+                               i++;
+                       } else if (args[i].equalsIgnoreCase("-ka") || args[i].equalsIgnoreCase("--keepalive")) {
+                               keepAliveValue = Integer.valueOf(args[i + 1]);
+                               i++;
+                       } else if (args[i].equalsIgnoreCase("--stateful")) {
+                               stateful = true;
+                       } else if (args[i].equalsIgnoreCase("--active")) {
+                               stateful = true;
+                               active = true;
+                       } else if (args[i].equalsIgnoreCase("--versioned")) {
+                               stateful = true;
+                               versioned = true;
+                       } else if (args[i].equalsIgnoreCase("--instant")) {
+                               stateful = true;
+                               instant = true;
+                               if (Integer.valueOf(args[i + 1]) > 0 && Integer.valueOf(args[i + 1]) < Integer.MAX_VALUE) {
+                                       timeout = Integer.valueOf(args[i + 1]);
+                                       i++;
+                               }
+                       } else if (args[i].equalsIgnoreCase("--autoResponseMessages") || args[i].equalsIgnoreCase("-arm")) {
+                               autoResponseMessagesSrc = args[i + 1];
+                               i++;
+                       } else if (args[i].equalsIgnoreCase("--periodicallySendMessages") || args[i].equalsIgnoreCase("-psm")) {
+                               periodicallySendMessagesSrc = args[i + 1];
+                               i++;
+                               period = Integer.valueOf(args[i + 1]);
+                               i++;
+                       } else if (args[i].equalsIgnoreCase("--sendNowMessage") || args[i].equalsIgnoreCase("-snm")) {
+                               sendNowMessageSrc = args[i + 1];
+                               i++;
+                       } else {
+                               System.out.println("WARNING: Unrecognized argument: " + args[i]);
+                       }
+                       i++;
+               }
+               if (deadTimerValue != 0 && deadTimerValue != keepAliveValue * 4) {
+                       System.out.println("WARNING: The value of DeadTimer should be 4 times the value of KeepAlive.");
+               }
+               if (deadTimerValue == 0) {
+                       deadTimerValue = keepAliveValue * 4;
+               }
+
+               final PCEPSessionListenerFactory slf = new TestingSessionListenerFactory(autoResponseMessagesSrc, periodicallySendMessagesSrc, period, sendNowMessageSrc);
+               final PCEPSessionProposalFactory spf = new PCEPSessionProposalFactoryImpl(deadTimerValue, keepAliveValue, stateful, active, versioned, instant, timeout);
+               final PCEPSessionProposalCheckerFactory spcf = new PCEPSessionProposalCheckerFactoryImpl();
+
+               final PCEPSessionProposal prefs = spf.getSessionProposal(address, 0);
+
+               final DispatcherImpl d = new DispatcherImpl(Executors.defaultThreadFactory());
+               final PCEPDispatcherImpl dispatcher = new PCEPDispatcherImpl(d, spf);
+
+               try {
+                       dispatcher.createServer(address, new PCEPConnectionFactory() {
+                               @Override
+                               public PCEPConnection createProtocolConnection(final InetSocketAddress address) {
+                                       final PCEPSessionProposalChecker checker = spcf.getPreferencesChecker(address);
+                                       final PCEPSessionListener lsnr = slf.getSessionListener(address.getAddress());
+
+                                       return new PCEPConnectionImpl(address, lsnr, prefs.getProposal(), checker);
+                               }
+
+                               @Override
+                               public void setProposal(final PCEPSessionProposalFactory proposals, final InetSocketAddress address, final int sessionId) {
+                               }
+                       });
+                       // final ProtocolServer s = dispatcher.createServer(address, slf, spf, spcf);
+
+                       // try {
+                       // Thread.sleep(10000);
+                       // } catch (final InterruptedException e) {
+                       // e.printStackTrace();
+                       // }
+                       //
+                       // s.close();
+
+               } finally {
+                       ((PCEPSessionProposalCheckerFactoryImpl) spcf).close();
+                       d.stop();
+               }
+       }
+}
diff --git a/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/MessageGeneratorService.java b/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/MessageGeneratorService.java
new file mode 100644 (file)
index 0000000..d8a3061
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.testtool;
+
+import java.util.Queue;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+
+public interface MessageGeneratorService {
+       public Queue<PCEPMessage> generateMessages();
+}
diff --git a/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/SessionListenerFactory.java b/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/SessionListenerFactory.java
new file mode 100644 (file)
index 0000000..027c8e6
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.testtool;
+
+import java.net.InetAddress;
+
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
+
+/**
+ *
+ */
+public class SessionListenerFactory extends PCEPSessionListenerFactory {
+
+       @Override
+       public PCEPSessionListener getSessionListener(InetAddress address) {
+               return new SimpleSessionListener();
+       }
+}
diff --git a/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/SimpleSessionListener.java b/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/SimpleSessionListener.java
new file mode 100644 (file)
index 0000000..fb9fdb5
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.testtool;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Simple Session Listener that is notified about messages and changes in the session.
+ */
+public class SimpleSessionListener extends PCEPSessionListener {
+
+       public List<PCEPMessage> messages = new ArrayList<PCEPMessage>();
+
+       public boolean up = false;
+
+       private static final Logger logger = LoggerFactory.getLogger(SimpleSessionListener.class);
+
+       public SimpleSessionListener() {
+       }
+
+       @Override
+       public void onMessage(PCEPSession session, PCEPMessage message) {
+               logger.debug("Received message: " + message);
+               this.messages.add(message);
+       }
+
+       @Override
+       public void onSessionUp(PCEPSession session, PCEPOpenObject local,
+                       PCEPOpenObject remote) {
+               logger.debug("Session up.");
+               this.up = true;
+               //this.notifyAll();
+       }
+
+       @Override
+       public void onSessionDown(PCEPSession session, PCEPCloseObject reason, Exception e) {
+               logger.debug("Session down.");
+               this.up = false;
+               //this.notifyAll();
+       }
+
+       @Override
+       public void onSessionTerminated(PCEPSession session,
+                       TerminationReason cause) {
+               logger.debug("Session terminated. Cause : " + cause.toString());
+       }
+}
diff --git a/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/TestingSessionListener.java b/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/TestingSessionListener.java
new file mode 100644 (file)
index 0000000..69e6334
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.testtool;
+
+import groovy.lang.GroovyClassLoader;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.message.PCEPXRAddTunnelMessage;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+public class TestingSessionListener extends PCEPSessionListener {
+
+       public List<PCEPMessage> messages = new ArrayList<PCEPMessage>();
+
+       private static final Logger logger = LoggerFactory.getLogger(TestingSessionListener.class);
+
+       public final Queue<PCEPMessage> replyMessages;
+       public final Queue<PCEPMessage> sendNowMessages;
+       public final Queue<PCEPMessage> periodicalMessages;
+       public final int period;
+
+       private class MessageTimer extends TimerTask {
+               private final PCEPMessage message;
+               private final PCEPSession session;
+
+               MessageTimer(final PCEPMessage message, final PCEPSession session) {
+                       this.message = message;
+                       this.session = session;
+               }
+
+               @Override
+               public void run() {
+                       this.session.sendMessage(this.message);
+               }
+       }
+
+       public TestingSessionListener() {
+               /**
+                * default messages are set to null
+                */
+               this.period = 0;
+               this.replyMessages = new LinkedList<PCEPMessage>();
+               this.sendNowMessages = new LinkedList<PCEPMessage>();
+               this.periodicalMessages = new LinkedList<PCEPMessage>();
+       }
+
+       public TestingSessionListener(final String autoResponseMessagesSrc, final String periodicallySendMessagesSrc, final int period,
+                       final String sendNowMessageSrc) {
+               this.period = period;
+               this.replyMessages = this.loadMessageGeneratorFromFile(autoResponseMessagesSrc).generateMessages();
+               this.sendNowMessages = this.loadMessageGeneratorFromFile(sendNowMessageSrc).generateMessages();
+               this.periodicalMessages = this.loadMessageGeneratorFromFile(periodicallySendMessagesSrc).generateMessages();
+       }
+
+       /**
+        * Periodically send messages from loaded queue.
+        * 
+        * @param session the session used to send message
+        * @param period the time between two sent messages
+        */
+       public void sendPeriodically(final PCEPSession session, final int seconds) {
+               if (!this.periodicalMessages.isEmpty()) {
+                       this.sendPeriodically(session, this.periodicalMessages.poll(), seconds);
+               } else
+                       logger.debug("DON'T starting PERIODICAL sender. Messages queue is empty.");
+       }
+
+       /**
+        * Periodically send specified message.
+        * 
+        * @param session the session used to send message
+        * @param message the message to send
+        * @param period the time between two sent messages
+        */
+       public void sendPeriodically(final PCEPSession session, final PCEPMessage message, final int seconds) {
+               final Timer timer = new Timer();
+
+               logger.debug("Starting periodical sending of messages with {} seconds delay.", seconds);
+               timer.schedule(new MessageTimer(message, session), seconds * 1000);
+       }
+
+       public void sendNow(final PCEPSession session) {
+               if (!this.sendNowMessages.isEmpty()) {
+                       final PCEPMessage msg = this.sendNowMessages.poll();
+                       this.sendNow(session, msg);
+               } else
+                       logger.debug("DON'T sending NOW. Messages queue is empty.");
+       }
+
+       public void sendNow(final PCEPSession session, final PCEPMessage message) {
+               logger.debug("Sending NOW.");
+               session.sendMessage(message);
+       }
+
+       @Override
+       public void onMessage(final PCEPSession session, final PCEPMessage message) {
+               logger.debug("Received message: " + message);
+               this.messages.add(message);
+
+               // if (!this.replyMessages.isEmpty()) {
+               // this.logger.debug("Remaining messages in queue: {}", this.replyMessages.size());
+               // session.sendMessage(this.replyMessages.poll());
+               // } else
+               // this.logger.debug("Reply messages queue is empty.");
+       }
+
+       @Override
+       public void onSessionUp(final PCEPSession session, final PCEPOpenObject local, final PCEPOpenObject remote) {
+               logger.debug("Session up.");
+               final List<ExplicitRouteSubobject> subs = new ArrayList<ExplicitRouteSubobject>();
+               subs.add(new EROIPPrefixSubobject<Prefix<?>>(new IPv4Prefix(new IPv4Address(new byte[] { 10, 1, 1, 2 }), 32), false));
+               subs.add(new EROIPPrefixSubobject<Prefix<?>>(new IPv4Prefix(new IPv4Address(new byte[] { 2, 2, 2, 2 }), 32), false));
+               session.sendMessage(new PCEPXRAddTunnelMessage(new PCEPLspObject(23, false, false, false, false), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(new byte[] {
+                               1, 1, 1, 1 }), new IPv4Address(new byte[] { 2, 2, 2, 2 })), new PCEPExplicitRouteObject(subs, false)));
+               this.sendNow(session);
+               this.sendPeriodically(session, this.period);
+       }
+
+       @Override
+       public void onSessionDown(final PCEPSession session, final PCEPCloseObject reason, final Exception e) {
+               logger.debug("Session down because: " + reason);
+               try {
+                       session.close();
+               } catch (final IOException ex) {
+                       logger.warn("Session could not be closed.", e);
+               }
+       }
+
+       @Override
+       public void onSessionTerminated(final PCEPSession session, final TerminationReason cause) {
+               logger.debug("Session terminated. Cause : " + cause.toString());
+       }
+
+       private MessageGeneratorService loadMessageGeneratorFromFile(final String path) {
+               try {
+                       final GroovyClassLoader l = new GroovyClassLoader();
+                       final Class<?> scriptClass = l.parseClass(new File(path));
+                       l.close();
+                       logger.debug("Loaded '{}'", path);
+                       final MessageGeneratorService generator = (MessageGeneratorService) scriptClass.newInstance();
+                       logger.debug("Instantiated '{}'", path);
+                       return generator;
+               } catch (final Exception e) {
+                       logger.error("Failed to load '{}'. Using empty queue.", path);
+                       return new MessageGeneratorService() {
+
+                               @Override
+                               public Queue<PCEPMessage> generateMessages() {
+                                       return new LinkedList<PCEPMessage>();
+                               }
+                       };
+               }
+
+       }
+
+       @SuppressWarnings("unused")
+       private MessageGeneratorService loadMessageGeneratorFormSysResource(final String path) {
+               try {
+                       final InputStream is = this.getClass().getResourceAsStream(path);
+                       final BufferedReader buffReader = new BufferedReader(new InputStreamReader(is));
+                       final StringBuilder script = new StringBuilder();
+                       String scriptLine;
+                       while ((scriptLine = buffReader.readLine()) != null) {
+                               script.append(scriptLine + "\n");
+                       }
+                       final GroovyClassLoader l = new GroovyClassLoader();
+                       final Class<?> scriptClass = l.parseClass(script.toString());
+                       l.close();
+                       logger.debug("Loaded '{}'", path);
+                       final MessageGeneratorService generator = (MessageGeneratorService) scriptClass.newInstance();
+                       logger.debug("Instantiated '{}'", path);
+                       return generator;
+
+               } catch (final Exception e) {
+                       logger.error("Failed to load '{}' from system resources. Using empty queue.", path);
+                       return new MessageGeneratorService() {
+
+                               @Override
+                               public Queue<PCEPMessage> generateMessages() {
+                                       return new LinkedList<PCEPMessage>();
+                               }
+                       };
+               }
+       }
+}
diff --git a/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/TestingSessionListenerFactory.java b/pcep/testtool/src/main/java/org/opendaylight/protocol/pcep/testtool/TestingSessionListenerFactory.java
new file mode 100644 (file)
index 0000000..9274e0c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.testtool;
+
+import java.net.InetAddress;
+
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
+
+/**
+ *
+ */
+public class TestingSessionListenerFactory extends PCEPSessionListenerFactory {
+
+       private final String autoResponseMessagesSrc;
+       private final String periodicallySendMessagesSrc;
+       private final String sendNowMessageSrc;
+       private final int period;
+
+       public TestingSessionListenerFactory(String autoResponseMessagesSrc, String periodicallySendMessagesSrc, int period, String sendNowMessageSrc) {
+               this.autoResponseMessagesSrc = autoResponseMessagesSrc;
+               this.periodicallySendMessagesSrc = periodicallySendMessagesSrc;
+               this.period = period;
+               this.sendNowMessageSrc = sendNowMessageSrc;
+       }
+
+       @Override
+       public PCEPSessionListener getSessionListener(InetAddress address) {
+               return new TestingSessionListener(this.autoResponseMessagesSrc, this.periodicallySendMessagesSrc, this.period, this.sendNowMessageSrc);
+       }
+
+}
diff --git a/pcep/testtool/src/main/resources/GroovyReplyMessageGenerator.groovy b/pcep/testtool/src/main/resources/GroovyReplyMessageGenerator.groovy
new file mode 100644 (file)
index 0000000..25be4c6
--- /dev/null
@@ -0,0 +1,39 @@
+import java.util.Queue
+
+import org.opendaylight.protocol.pcep.PCEPMessage
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject
+import org.opendaylight.protocol.pcep.tool.MessageGeneratorService
+
+class GroovyReplyMessageGenerator implements MessageGeneratorService {
+       
+       public GroovyReplyMessageGenerator() {
+               }
+       
+       @Override
+       public Queue<PCEPMessage> generateMessages() {
+               def queue = new LinkedList<PCEPMessage>()
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+
+               queue.push(
+                       new PCEPReplyMessage(
+                               [
+                                       new CompositeResponseObject(
+                                               new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+                                       )
+                               ]
+                       )
+               )
+                               
+               return queue
+       }
+}
\ No newline at end of file
diff --git a/pcep/testtool/src/test/java/org/opendaylight/protocol/pcep/testtool/PCCMock.java b/pcep/testtool/src/test/java/org/opendaylight/protocol/pcep/testtool/PCCMock.java
new file mode 100644 (file)
index 0000000..8236bae
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.testtool;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposal;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.impl.PCEPDispatcherImpl;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import com.google.common.collect.Lists;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.concurrent.Executors;
+
+public class PCCMock {
+
+       public static void main(final String[] args) throws IOException, InterruptedException {
+               final List<PCEPTlv> tlvs = Lists.newArrayList();
+               tlvs.add(new NodeIdentifierTlv(new byte[] { (byte) 127, (byte) 2, (byte) 3, (byte) 7 }));
+               final PCEPSessionPreferences prop = new PCEPSessionPreferences(new PCEPOpenObject(30, 120, 0, tlvs));
+               final DispatcherImpl di = new DispatcherImpl(Executors.defaultThreadFactory());
+               final PCEPDispatcherImpl d = new PCEPDispatcherImpl(di, new PCEPSessionProposalFactory() {
+
+                       @Override
+                       public PCEPSessionProposal getSessionProposal(final InetSocketAddress address, final int sessionId) {
+                               return new PCEPSessionProposal() {
+
+                                       @Override
+                                       public PCEPSessionPreferences getProposal() {
+                                               return prop;
+                                       }
+                               };
+                       }
+               });
+
+               try {
+
+                       final PCEPSessionProposalChecker check = new PCEPSessionProposalChecker() {
+                               @Override
+                               public Boolean checkSessionCharacteristics(final SessionPreferences openObj) {
+                                       return true;
+                               }
+
+                               @Override
+                               public PCEPSessionPreferences getNewProposal(final SessionPreferences open) {
+                                       return new PCEPSessionPreferences(new PCEPOpenObject(30, 120, 0, null));
+                               }
+                       };
+
+                       d.createClient(new PCEPConnection() {
+                               @Override
+                               public InetSocketAddress getPeerAddress() {
+                                       return new InetSocketAddress("127.0.0.1", 4189);
+                               }
+
+                               @Override
+                               public PCEPSessionProposalChecker getProposalChecker() {
+                                       return check;
+                               }
+
+                               @Override
+                               public PCEPSessionPreferences getProposal() {
+                                       return prop;
+                               }
+
+                               @Override
+                               public PCEPSessionListener getListener() {
+                                       return new SimpleSessionListener();
+                               }
+                       });
+                       // Thread.sleep(5000);
+                       // final List<CompositeRequestObject> cro = new ArrayList<CompositeRequestObject>();
+                       // cro.add(new CompositeRequestObject(new PCEPRequestParameterObject(false, true, true, true, true, (short)
+                       // 4, 123, false, false),
+                       // new PCEPEndPointsObject<IPv4Address>(new IPv4Address(InetAddress.getByName("10.0.0.3")), new
+                       // IPv4Address(InetAddress.getByName("10.0.0.5")))));
+                       // for (int i = 0; i < 3; i++) {
+                       // Thread.sleep(1000);
+                       // session.sendMessage(new PCEPRequestMessage(cro));
+                       // }
+                       // Thread.sleep(5000);
+                       // Thread.sleep(1000);
+
+               } finally {
+                       di.stop();
+               }
+       }
+}
diff --git a/pcep/testtool/src/test/java/org/opendaylight/protocol/pcep/testtool/PCEPTestingToolTest.java b/pcep/testtool/src/test/java/org/opendaylight/protocol/pcep/testtool/PCEPTestingToolTest.java
new file mode 100644 (file)
index 0000000..5a03132
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.pcep.testtool;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+
+public class PCEPTestingToolTest {
+
+       @Test
+       public void testSimpleSessionListener() {
+               final SimpleSessionListener ssl = new SimpleSessionListener();
+               assertEquals(0, ssl.messages.size());
+               ssl.onMessage(null, new PCEPKeepAliveMessage());
+               assertEquals(1, ssl.messages.size());
+               assertTrue(ssl.messages.get(0) instanceof PCEPKeepAliveMessage);
+               assertFalse(ssl.up);
+               ssl.onSessionUp(null, null, null);
+               assertTrue(ssl.up);
+               ssl.onSessionDown(null, null, null);
+               assertFalse(ssl.up);
+       }
+
+       @Test
+       public void testSessionListenerFactory() {
+               assertTrue(new SessionListenerFactory().getSessionListener(null) instanceof SimpleSessionListener);
+       }
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644 (file)
index 0000000..1b8c047
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <name>OpenDaylight protocols</name>
+       <url>index.html</url>
+       <modelVersion>4.0.0</modelVersion>
+       <groupId>org.opendaylight.protocol</groupId>
+       <artifactId>protocol-parent</artifactId>
+       <description>OpenDaylight BGP+PCEP protocol parent</description>
+       <version>0.1</version>
+       <packaging>pom</packaging>
+       <properties>
+               <java.version.source>1.7</java.version.source>
+               <java.version.target>1.7</java.version.target>
+               <jacoco.version>0.6.2.201302030002</jacoco.version>
+               <commons.io.version>2.4</commons.io.version>
+               <checkstyle.version>2.9.1</checkstyle.version>
+               <pmd.version>2.7.1</pmd.version>
+               <dependency.version>2.8</dependency.version>
+               <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               <cxf.version>2.6.5</cxf.version>
+               <slf4j.version>1.7.2</slf4j.version>
+               <logback.version>1.0.7</logback.version>
+               <junit.version>4.10</junit.version>
+               <maven.compiler.version>2.5.1</maven.compiler.version>
+               <maven.bundle.version>2.3.7</maven.bundle.version>
+               <jgrapht.version>0.8.3-SNAPSHOT</jgrapht.version>
+               <surefire.version>2.14.1</surefire.version>
+               <commonscodec.version>1.7</commonscodec.version>
+               <guava.version>13.0.1</guava.version>
+               <osgi.version>5.0.0</osgi.version>
+               <osgi.compendium.version>4.0.0</osgi.compendium.version>
+       </properties>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <modules>
+               <module>bgp</module>
+               <module>concepts</module>
+               <module>framework</module>
+               <module>mockito-configuration</module>
+               <module>pcep</module>
+               <module>util</module>
+       </modules>
+
+       <dependencies>
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <version>${junit.version}</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>ch.qos.logback</groupId>
+                       <artifactId>logback-classic</artifactId>
+                       <version>${logback.version}</version>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+       
+       <reporting>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-javadoc-plugin</artifactId>
+                               <version>2.8.1</version>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.jacoco</groupId>
+                               <artifactId>jacoco-maven-plugin</artifactId>
+                               <version>${jacoco.version}</version>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>2.9.1</version>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-pmd-plugin</artifactId>
+                               <version>${pmd.version}</version>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-antrun-plugin</artifactId>
+                               <version>${maven.antrun.version}</version>
+                       </plugin>
+               </plugins>
+       </reporting>
+
+       <distributionManagement>
+               <site>
+                       <id>${project.artifactId}</id>
+                       <name>NPS-APPLICATION Project site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+               <!-- mock repository to allow deploy phase without real deployment -->
+               <repository>
+                       <id>targetRepo</id>
+                       <name>Target folder as mock repository</name>
+                       <url>file://${basedir}/target/deploy</url>
+               </repository>
+       </distributionManagement>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-compiler-plugin</artifactId>
+                               <version>${maven.compiler.version}</version>
+                               <configuration>
+                                       <source>${java.version.source}</source>
+                                       <target>${java.version.target}</target>
+                                       <testSource>${java.version.source}</testSource>
+                                       <testTarget>${java.version.target}</testTarget>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.jacoco</groupId>
+                               <artifactId>jacoco-maven-plugin</artifactId>
+                               <version>${jacoco.version}</version>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>prepare-agent</goal>
+                                               </goals>
+                                       </execution>
+                                       <execution>
+                                               <id>report</id>
+                                               <phase>prepare-package</phase>
+                                               <goals>
+                                                       <goal>check</goal>
+                                                       <goal>report</goal>
+                                               </goals>
+                                               <configuration>
+                                                       <outputDirectory>${basedir}/target/jacoco</outputDirectory>
+                                                       <haltOnFailure>false</haltOnFailure>
+                                                       <check>
+                                                               <classRatio>80</classRatio>
+                                                       </check>
+                                               </configuration>
+                                       </execution>
+                               </executions>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-checkstyle-plugin</artifactId>
+                               <version>2.9.1</version>
+                               <configuration>
+                                       <configLocation>build/checkstyle/checkstyle-checker.xml</configLocation>
+                                       <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-surefire-plugin</artifactId>
+                               <version>${surefire.version}</version>
+                               <configuration>
+                                       <redirectTestOutputToFile>true</redirectTestOutputToFile>
+                                       <parallel>classes</parallel>
+                                       <forkCount>1C</forkCount>
+                                       <reuseForks>false</reuseForks>
+                                       <perCoreThreadCount>true</perCoreThreadCount>
+                                       <threadCount>2</threadCount>
+                               </configuration>
+                       </plugin>
+
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-pmd-plugin</artifactId>
+                               <version>${pmd.version}</version>
+                               <configuration>
+                                       <targetJdk>${java.version.target}</targetJdk>
+                                       <rulesets>
+                                               <ruleset>rulesets/basic.xml</ruleset>
+                                               <ruleset>rulesets/finalizers.xml</ruleset>
+                                               <ruleset>rulesets/imports.xml</ruleset>
+                                               <ruleset>rulesets/junit.xml</ruleset>
+                                               <!--ruleset>rulesets/optimizations.xml</ruleset -->
+                                               <ruleset>rulesets/strings.xml</ruleset>
+                                               <ruleset>rulesets/unusedcode.xml</ruleset>
+                                       </rulesets>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-dependency-plugin</artifactId>
+                               <version>${dependency.version}</version>
+                               <configuration>
+                                       <!--failOnWarning>true</failOnWarning -->
+                                       <ignoreNonCompile>true</ignoreNonCompile>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.fusesource.mvnplugins</groupId>
+                               <artifactId>maven-graph-plugin</artifactId>
+                               <version>1.4</version>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.codehaus.mojo</groupId>
+                               <artifactId>build-helper-maven-plugin</artifactId>
+                               <version>1.8</version>
+                       </plugin>
+               </plugins>
+               <pluginManagement>
+                       <plugins>
+                               <!--This plugin's configuration is used to store Eclipse m2e settings
+                                       only. It has no influence on the Maven build itself. -->
+                               <plugin>
+                                       <groupId>org.eclipse.m2e</groupId>
+                                       <artifactId>lifecycle-mapping</artifactId>
+                                       <version>1.0.0</version>
+                                       <configuration>
+                                               <lifecycleMappingMetadata>
+                                                       <pluginExecutions>
+                                                               <pluginExecution>
+                                                                       <pluginExecutionFilter>
+                                                                               <groupId>org.jacoco</groupId>
+                                                                               <artifactId>
+                                                                                       jacoco-maven-plugin
+                                                                               </artifactId>
+                                                                               <versionRange>
+                                                                                       [0.6.2.201302030002,)
+                                                                               </versionRange>
+                                                                               <goals>
+                                                                                       <goal>prepare-agent</goal>
+                                                                               </goals>
+                                                                       </pluginExecutionFilter>
+                                                                       <action>
+                                                                               <ignore></ignore>
+                                                                       </action>
+                                                               </pluginExecution>
+                                                               <pluginExecution>
+                                                                       <pluginExecutionFilter>
+                                                                               <groupId>pl.project13.maven</groupId>
+                                                                               <artifactId>git-commit-id-plugin</artifactId>
+                                                                               <versionRange>
+                                                                                       [2.1.4,)
+                                                                               </versionRange>
+                                                                               <goals>
+                                                                                       <goal>revision</goal>
+                                                                               </goals>
+                                                                       </pluginExecutionFilter>
+                                                                       <action>
+                                                                               <ignore></ignore>
+                                                                       </action>
+                                                               </pluginExecution>
+                                                       </pluginExecutions>
+                                               </lifecycleMappingMetadata>
+                                       </configuration>
+                               </plugin>
+                       </plugins>
+               </pluginManagement>
+       </build>
+
+       <pluginRepositories>
+               <pluginRepository>
+                       <id>mvnplugins.fusesource.org</id>
+                       <url>http://mvnplugins.fusesource.org/repo/release</url>
+                       <releases>
+                               <enabled>true</enabled>
+                       </releases>
+               </pluginRepository>
+       </pluginRepositories>
+</project>
diff --git a/src/site/apt/index.apt.vm b/src/site/apt/index.apt.vm
new file mode 100644 (file)
index 0000000..d5576e6
--- /dev/null
@@ -0,0 +1,7 @@
+
+About ${project.artifactId}
+
+---
+${project.description} 
+Project main site.
+---
diff --git a/src/site/site.xml b/src/site/site.xml
new file mode 100644 (file)
index 0000000..c809a91
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+  <body>
+    <head>${project.artifactId}</head>
+    <links>
+      <item name="${project.artifactId}" href="index.html"/>
+    </links>
+
+    <menu ref="modules"/>
+
+    <menu ref="reports"/>
+
+    
+  </body>
+</project>
+
diff --git a/util/.gitignore b/util/.gitignore
new file mode 100644 (file)
index 0000000..fc1d35e
--- /dev/null
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
diff --git a/util/.project b/util/.project
new file mode 100644 (file)
index 0000000..fd7d848
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>nps-util</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/util/pom.xml b/util/pom.xml
new file mode 100644 (file)
index 0000000..4a393c0
--- /dev/null
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.protocol</groupId>
+               <artifactId>protocol-parent</artifactId>
+               <version>0.1</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>util</artifactId>
+       <description>Protocol utilities</description>
+       <packaging>bundle</packaging>
+       <version>1.0</version>
+       <name>${project.artifactId}</name>
+       <prerequisites>
+               <maven>3.0.4</maven>
+       </prerequisites>
+
+       <dependencies>
+               <dependency>
+                       <groupId>com.google.guava</groupId>
+                       <artifactId>guava</artifactId>
+                       <version>${guava.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>commons-codec</groupId>
+                       <artifactId>commons-codec</artifactId>
+                       <version>${commonscodec.version}</version>
+               </dependency>
+    </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${maven.bundle.version}</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                                               <Import-Package>
+                            com.google.common.*, 
+                            javax.net.ssl,
+                            org.apache.commons.codec.binary,
+                                               </Import-Package>
+                                               <Export-Package>
+                                                       org.opendaylight.protocol.util
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-jar-plugin</artifactId>
+                               <version>2.4</version>
+                               <executions>
+                                       <execution>
+                                               <phase>package</phase>
+                                               <goals>
+                                                       <goal>test-jar</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <distributionManagement>
+               <site>
+                       <id>util</id>
+                       <name>NPS-UTIL Module site</name>
+                       <url>${basedir}/target/site/${project.artifactId}</url>
+               </site>
+       </distributionManagement>
+</project>
diff --git a/util/src/main/java/org/opendaylight/protocol/util/ByteArray.java b/util/src/main/java/org/opendaylight/protocol/util/ByteArray.java
new file mode 100644 (file)
index 0000000..74052bc
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.apache.commons.codec.binary.Hex;
+
+/**
+ *
+ * Util class for methods working with byte array.
+ *
+ */
+public final class ByteArray {
+       private ByteArray() {
+       }
+
+       /**
+        * Returns a new byte array from given byte array, starting at start index
+        * with the size of the length parameter. Byte array given as parameter
+        * stays untouched.
+        *
+        * @param bytes
+        *            original byte array
+        * @param startIndex
+        *            beginning index, inclusive
+        * @param length
+        *            how many bytes should be in the sub-array
+        * @return a new byte array that is a sub-array of the original
+        */
+       public static byte[] subByte(final byte[] bytes, int startIndex, int length) {
+               if (bytes.length == 0 || length < 0 || length > bytes.length || startIndex < 0 || startIndex > bytes.length || startIndex + length > bytes.length) {
+                       throw new IllegalArgumentException("Cannot create subByte, invalid arguments: Length: " + length + " startIndex: " + startIndex);
+               }
+               final byte[] res = new byte[length];
+               System.arraycopy(bytes, startIndex, res, 0, length);
+               return res;
+       }
+
+       /**
+        * Converts byte array to Integer. If there are less bytes in the array as
+        * required (4), the method will push adequate number of zero bytes
+        * prepending given byte array.
+        *
+        * @param bytes
+        *            array to be converted to int
+        * @return int
+        */
+       public static int bytesToInt(byte[] bytes) {
+               if (bytes.length > Integer.SIZE / 8) {
+                       throw new IllegalArgumentException("Cannot convert bytes to integer. Byte array too big.");
+               }
+               byte[] res = new byte[Integer.SIZE / 8];
+               if (bytes.length != Integer.SIZE / 8) {
+                       System.arraycopy(bytes, 0, res, Integer.SIZE / 8 - bytes.length, bytes.length);
+               } else {
+                       res = bytes;
+               }
+               final ByteBuffer buff = ByteBuffer.wrap(res);
+               return buff.getInt();
+       }
+
+       /**
+        * Converts byte array to long. If there are less bytes in the array as
+        * required (Long.Size), the method will push adequate number of zero bytes
+        * prepending given byte array.
+        *
+        * @param bytes
+        *            array to be converted to long
+        * @return long
+        */
+       public static long bytesToLong(byte[] bytes) {
+               if (bytes.length > Long.SIZE / 8) {
+                       throw new IllegalArgumentException("Cannot convert bytes to long.Byte array too big.");
+               }
+               byte[] res = new byte[Long.SIZE / 8];
+               if (bytes.length != Long.SIZE / 8) {
+                       System.arraycopy(bytes, 0, res, Long.SIZE / 8 - bytes.length, bytes.length);
+               } else {
+                       res = bytes;
+               }
+               final ByteBuffer buff = ByteBuffer.wrap(res);
+               return buff.getLong();
+       }
+
+       /**
+        * Converts byte array to float IEEE 754 format. If there are less bytes in
+        * the array as required (Float.Size), the method will push adequate number
+        * of zero bytes prepending given byte array.
+        *
+        * @param bytes
+        *            array to be converted to float
+        * @return float
+        */
+       public static float bytesToFloat(byte[] bytes) {
+               if (bytes.length > Float.SIZE / 8) {
+                       throw new IllegalArgumentException("Cannot convert bytes to float.Byte array too big.");
+               }
+               byte[] res = new byte[Float.SIZE / 8];
+               if (bytes.length != Float.SIZE / 8) {
+                       System.arraycopy(bytes, 0, res, Float.SIZE / 8 - bytes.length, bytes.length);
+               } else {
+                       res = bytes;
+               }
+               final ByteBuffer buff = ByteBuffer.wrap(res);
+               return buff.getFloat();
+       }
+
+       /**
+        * Cuts 'count' number of bytes from the beginning of given byte array.
+        *
+        * @param bytes
+        *            array to be cut, cannot be null
+        * @param count
+        *            how many bytes needed to be cut, needs to be > 0
+        * @return bytes array without first 'count' bytes
+        */
+       public static byte[] cutBytes(byte[] bytes, int count) {
+               if (bytes.length == 0 || count > bytes.length || count <= 0) {
+                       throw new IllegalArgumentException("Cannot cut bytes, invalid arguments: Count: " + count + " bytes.length: " + bytes.length);
+               }
+               return Arrays.copyOfRange(bytes, count, bytes.length);
+       }
+
+       /**
+        * Parse byte to bits, from the leftmost bit.
+        *
+        * @param b
+        *            byte to be parsed
+        * @return array of booleans with size of 8
+        */
+       public static boolean[] parseBits(byte b) {
+               final boolean[] bits = new boolean[Byte.SIZE];
+               int j = 0;
+               for (int i = Byte.SIZE - 1; i >= 0; i--) {
+                       bits[j] = ((b & (1 << i)) != 0);
+                       j++;
+               }
+               return bits;
+       }
+
+       /**
+        * Parses array of bytes to BitSet, from left most bit.
+        *
+        * @param bytes
+        *            array of bytes to be parsed
+        * @return BitSet with length = bytes.length * Byte.SIZE
+        */
+       public static BitSet bytesToBitSet(byte[] bytes) {
+               final BitSet bitSet = new BitSet(bytes.length * Byte.SIZE);
+               for (int bytes_iter = 0; bytes_iter < bytes.length; bytes_iter++) {
+                       final int offset = bytes_iter * Byte.SIZE;
+                       for (int byte_iter = Byte.SIZE - 1; byte_iter >= 0; byte_iter--) {
+                               bitSet.set(offset + (Byte.SIZE - byte_iter - 1), (bytes[bytes_iter] & 1 << (byte_iter)) != 0);
+                       }
+               }
+               return bitSet;
+       }
+
+       /**
+        * Parses BitSet to bytes, from most left bit.
+        *
+        * @param bitSet
+        *            BitSet to be parsed
+        * @param returnedLength
+        *            Length of returned array. Overlapping flags are truncated.
+        * @return parsed array of bytes with length of bitSet.length / Byte.SIZE
+        */
+       public static byte[] bitSetToBytes(BitSet bitSet, int returnedLength) {
+               final byte[] bytes = new byte[returnedLength];
+
+               for (int bytes_iter = 0; bytes_iter < bytes.length; bytes_iter++) {
+                       final int offset = bytes_iter * Byte.SIZE;
+
+                       for (int byte_iter = Byte.SIZE - 1; byte_iter >= 0; byte_iter--) {
+                               bytes[bytes_iter] |= (bitSet.get(offset + (Byte.SIZE - byte_iter - 1)) ? 1 << byte_iter : 0);
+                       }
+               }
+               return bytes;
+       }
+
+       /**
+        * Parses file to array of bytes
+        *
+        * @param name
+        *            path to file to by parsed
+        * @return parsed array of bytes
+        */
+       public static byte[] fileToBytes(String name) throws IOException {
+               final File file = new File(name);
+               int offset = 0;
+               int numRead = 0;
+
+               if (file.length() > Integer.MAX_VALUE) {
+                       throw new IOException("Too large file to load in byte array.");
+               }
+
+               final FileInputStream fin = new FileInputStream(file);
+               final byte[] byteArray = new byte[(int) file.length()];
+
+               while (offset < byteArray.length && (numRead = fin.read(byteArray, offset, byteArray.length - offset)) >= 0) {
+                       offset += numRead;
+               }
+
+               if (fin != null) {
+                       fin.close();
+               }
+
+               return byteArray;
+       }
+
+       /**
+        * Parses integer to array of bytes
+        *
+        * @param num
+        *            integer to be parsed
+        * @return parsed array of bytes with length of Integer.SIZE/Byte.SIZE
+        */
+       public static byte[] intToBytes(int num) {
+               final ByteBuffer bytesBuffer = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE);
+               bytesBuffer.putInt(num);
+
+               return bytesBuffer.array();
+       }
+
+       /**
+        * Parses integer to array of bytes
+        *
+        * @param num
+        *            integer to be parsed
+        * @return parsed array of bytes with length of Long.SIZE/Byte.SIZE
+        */
+       public static byte[] longToBytes(long num) {
+               final ByteBuffer bytesBuffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
+               bytesBuffer.putLong(num);
+
+               return bytesBuffer.array();
+       }
+
+       /**
+        * Copies range of bits from passed byte and align to right.<br/>
+        *
+        * @param src
+        *            source byte to copy from
+        * @param fromBit
+        *            bit from which will copy (inclusive) - numbered from 0
+        * @param length
+        *            of bits to by copied - <1,8>
+        * @return copied value aligned to right
+        */
+       public static byte copyBitsRange(byte src, int fromBit, int length) {
+               if (fromBit < 0 | fromBit > Byte.SIZE - 1 | length < 1 | length > Byte.SIZE) {
+                       throw new IllegalArgumentException("fromBit or toBit is out of range.");
+               }
+               if (fromBit + length > Byte.SIZE) {
+                       throw new IllegalArgumentException("Out of range.");
+               }
+
+               byte retByte = 0;
+               int retI = 0;
+
+               for (int i = fromBit + length - 1; i >= fromBit; i--) {
+
+                       if ((src & 1 << (Byte.SIZE - i - 1)) != 0) {
+                               retByte |= 1 << retI;
+                       }
+
+                       retI++;
+               }
+
+               return retByte;
+       }
+
+       /**
+        * Copies whole source byte array to destination from offset.<br/>
+        * Length of src can't be bigger than dest length minus offset
+        *
+        * @param src
+        *            byte[]
+        * @param dest
+        *            byte[]
+        * @param offset
+        *            int
+        */
+       public static void copyWhole(byte[] src, byte[] dest, int offset) {
+               if (dest.length - offset < src.length) {
+                       throw new ArrayIndexOutOfBoundsException("Can't copy whole array.");
+               }
+
+               System.arraycopy(src, 0, dest, offset, src.length);
+       }
+
+       /**
+        * Convert array of bytes to java short.<br/>
+        * Size can't be bigger than size of short in bytes.
+        *
+        * @param bytes
+        *            byte[]
+        * @return array of bytes
+        */
+       public static short bytesToShort(byte[] bytes) {
+               if (bytes.length > Short.SIZE / Byte.SIZE) {
+                       throw new IllegalArgumentException("Cannot convert bytes to short. Byte array too big.");
+               }
+               byte[] res = new byte[Short.SIZE / Byte.SIZE];
+               if (bytes.length != Short.SIZE / Byte.SIZE) {
+                       System.arraycopy(bytes, 0, res, Integer.SIZE / Byte.SIZE - bytes.length, bytes.length);
+               } else {
+                       res = bytes;
+               }
+               final ByteBuffer buff = ByteBuffer.wrap(res);
+               return buff.getShort();
+       }
+
+       /**
+        * Convert short java representation to array of bytes.
+        *
+        * @param num
+        *            short
+        * @return short represented as array of bytes
+        */
+       public static byte[] shortToBytes(short num) {
+               final ByteBuffer bytesBuffer = ByteBuffer.allocate(Short.SIZE / Byte.SIZE);
+               bytesBuffer.putShort(num);
+
+               return bytesBuffer.array();
+       }
+
+       /**
+        * Convert float java representation to array of bytes.
+        *
+        * @param num
+        *            float
+        * @return float represented as array of bytes
+        */
+       public static byte[] floatToBytes(float num) {
+               final ByteBuffer bytesBuffer = ByteBuffer.allocate(Float.SIZE / Byte.SIZE);
+               bytesBuffer.putFloat(num);
+
+               return bytesBuffer.array();
+       }
+
+       /**
+        * Pretty print array of bytes as hex encoded string with 16 bytes per line.
+        * Each byte is separated by space, after first 8 bytes there are 2 spaces
+        * instead of one.
+        */
+       public static String bytesToHexString(byte[] array) {
+               return bytesToHexString(array, 16, " ", 8, " ");
+       }
+
+       /**
+        * Pretty-print an array of bytes as hex-encoded string. Separate them
+        * with specified separator.
+        */
+       public static String toHexString(final byte[] array, final String separator) {
+               final StringBuilder sb = new StringBuilder();
+               for (int i = 0; i < array.length; i++) {
+                       sb.append(Hex.encodeHexString(new byte[] { array[i] }));
+                       if (i + 1 != array.length)
+                               sb.append(separator);
+               }
+               return sb.toString();
+       }
+
+       /**
+        * Convert array of bytes to hexadecimal String.
+        *
+        * @param array
+        * @param bytesOnLine
+        *            number of bytes that should by displayed in one line
+        * @param byteSeparator
+        *            string that will be placed after each byte
+        * @param wordCount
+        *            number of bytes that make a 'word' (group of bytes)
+        * @param wordSeparator
+        *            string that will be placed after each word
+        * @return Hexadecimal string representation of given byte array
+        */
+       public static String bytesToHexString(byte[] array, int bytesOnLine, String byteSeparator, int wordCount, String wordSeparator) {
+               final StringBuilder sb = new StringBuilder();
+               for (int i = 0; i < array.length; i++) {
+                       sb.append(Hex.encodeHexString(new byte[] { array[i] }));
+                       if ((i + 1) % bytesOnLine == 0) {
+                               sb.append("\n");
+                       } else {
+                               sb.append(byteSeparator);
+                               if ((i + 1) % wordCount == 0) {
+                                       sb.append(wordSeparator);
+                               }
+                       }
+
+               }
+               return sb.toString();
+       }
+
+       /**
+        * Decodes bytes to human readable UTF-8 string. If bytes are not valid
+        * UTF-8, they are represented as raw binary.
+        *
+        * @param bytes
+        *            bytes to be decoded to string
+        * @return String representation of passed bytes
+        */
+       public static String bytesToHRString(byte[] bytes) {
+               try {
+                       return Charset.forName("UTF-8").newDecoder().decode(ByteBuffer.wrap(bytes)).toString();
+               } catch (final CharacterCodingException e) {
+                       return Arrays.toString(bytes);
+               }
+       }
+
+       /**
+        * Searches for byte sequence in given array. Returns the index of first occurrence of
+        * this sequence (where it starts).
+        * @param bytes byte array where to search for sequence
+        * @param sequence to be searched in given byte array
+        * @return -1 if the sequence could not be found in given byte array
+        *                      int index of first occurrence of the sequence in bytes
+        */
+       public static int findByteSequence(byte[] bytes, byte[] sequence) {
+               if (bytes.length < sequence.length)
+                       throw new IllegalArgumentException("Sequence to be found is longer than the given byte array.");
+               if (bytes.length == sequence.length)
+                       if (Arrays.equals(bytes, sequence))
+                               return 0;
+                       else
+                               return -1;
+               int j = 0;
+               for (int i = 0; i < bytes.length; i++) {
+                       if (bytes[i] == sequence[j]) {
+                               j++;
+                               if (j == sequence.length)
+                                       return i - j + 1;
+                       } else
+                               j = 0;
+               }
+               return -1;
+       }
+
+       private static final byte maskBits[] = new byte[] { 0, -128, -64, -32, -16, -8, -4, -2 };
+       public static final byte[] maskBytes(final byte[] original,
+                       final int bits) {
+               if (original.length * 8 < bits)
+                       throw new IllegalArgumentException("Attempted to apply invalid mask (too long)");
+
+               final int needbytes = (bits +7) / 8;
+               // We need to have a new copy of the underlying byte array, so that
+               // the original bytes stay untouched
+               final byte[] bytes = Arrays.copyOf(original, original.length);
+
+               final int needmask = bits % 8;
+               if (needmask != 0)
+                       bytes[needbytes-1] &= maskBits[needmask];
+
+               // zero-out  the rest of the bytes
+               for (int i = needbytes ; i < bytes.length; i++) {
+                       bytes[i] = 0;
+               }
+               return bytes;
+       }
+}
diff --git a/util/src/main/java/org/opendaylight/protocol/util/DefaultingTypesafeContainer.java b/util/src/main/java/org/opendaylight/protocol/util/DefaultingTypesafeContainer.java
new file mode 100644 (file)
index 0000000..8110091
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.util;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Extension of the TypesafeContainer which supports the notion of a default
+ * key.
+ *
+ * @param <S> Supertype of all objects stored in this container
+ */
+public class DefaultingTypesafeContainer<S> extends TypesafeContainer<S> {
+       private static final long serialVersionUID = 140170613440644179L;
+       private Class<? extends S> defaultKey = null;
+
+       /**
+        * Returns the default entry.
+        *
+        * @return Default entry, or null if no default was set
+        */
+       public S getDefaultEntry() {
+               if (defaultKey == null) {
+                       return null;
+               }
+               return defaultKey.cast(getEntry(defaultKey));
+       }
+
+       /**
+        * Sets or resets the default entry.
+        *
+        * @param entry Default entry value. Use null to reset the container
+        *        to no default entry.
+        */
+       public void setDefaultEntry(final S entry) {
+               if (defaultKey != null) {
+                       removeEntry(defaultKey);
+                       defaultKey = null;
+               }
+               if (entry != null) {
+                       /*
+                        * This is rather obvious: entry is required to be a subclass
+                        * of T. This implies that its class conforms to
+                        * Class<? extends T>. For some reason, the compiler is not
+                        * smart enough to know this.
+                        */
+                       @SuppressWarnings("unchecked")
+                       final Class<? extends S> c = (Class<? extends S>) entry.getClass();
+                       defaultKey = c;
+
+                       setEntry(defaultKey, entry);
+               }
+       }
+
+       @Override
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("defaultKey", this.defaultKey);
+               return super.addToStringAttributes(toStringHelper);
+       }
+
+       @Override
+       public int hashCode() {
+               return super.hashCode() * 7 + (defaultKey != null ? defaultKey.hashCode() : 0);
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (obj instanceof DefaultingTypesafeContainer == false) {
+                       return false;
+               }
+               if (obj == this) {
+                       return true;
+               }
+               if (super.equals(obj)==false) {
+                       return false;
+               }
+               Object thatDefaultKey = ((DefaultingTypesafeContainer<?>)obj).defaultKey;
+               if (defaultKey == thatDefaultKey) {
+            return true;
+        }
+        if ((defaultKey == null) != (thatDefaultKey == null)) {
+            return false;
+        }
+        return thatDefaultKey.equals(thatDefaultKey);
+       }
+
+}
diff --git a/util/src/main/java/org/opendaylight/protocol/util/RemoveOnlySet.java b/util/src/main/java/org/opendaylight/protocol/util/RemoveOnlySet.java
new file mode 100644 (file)
index 0000000..cc41f64
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.util;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+
+public class RemoveOnlySet<E> implements Set<E> {
+       private final Set<E> set;
+
+       public RemoveOnlySet(final Set<E> set) {
+               this.set = set;
+       }
+
+       public static <T> RemoveOnlySet<T> wrap(final Set<T> set) {
+               return new RemoveOnlySet<T>(set);
+       }
+
+       @Override
+       public boolean add(final E e) {
+               throw new UnsupportedOperationException("Set does not accept additions");
+       }
+
+       @Override
+       public boolean addAll(final Collection<? extends E> c) {
+               throw new UnsupportedOperationException("Set does not accept additions");
+       }
+
+       @Override
+       public void clear() {
+               set.clear();
+       }
+
+       @Override
+       public boolean contains(final Object o) {
+               return set.contains(o);
+       }
+
+       @Override
+       public boolean containsAll(final Collection<?> c) {
+               return set.containsAll(c);
+       }
+
+       @Override
+       public boolean isEmpty() {
+               return set.isEmpty();
+       }
+
+       @Override
+       public Iterator<E> iterator() {
+               return set.iterator();
+       }
+
+       @Override
+       public boolean remove(final Object o) {
+               return set.remove(o);
+       }
+
+       @Override
+       public boolean removeAll(final Collection<?> c) {
+               return set.removeAll(c);
+       }
+
+       @Override
+       public boolean retainAll(final Collection<?> c) {
+               return set.retainAll(c);
+       }
+
+       @Override
+       public int size() {
+               return set.size();
+       }
+
+       @Override
+       public Object[] toArray() {
+               return set.toArray();
+       }
+
+       @Override
+       public <T> T[] toArray(final T[] a) {
+               return set.toArray(a);
+       }
+}
diff --git a/util/src/main/java/org/opendaylight/protocol/util/SSLUtil.java b/util/src/main/java/org/opendaylight/protocol/util/SSLUtil.java
new file mode 100644 (file)
index 0000000..106b3b1
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.util;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class SSLUtil {
+       public static SSLContext initializeSecureContext(
+                       final String pass, final InputStream ksKeysFile,
+                       final InputStream ksTrustFile, final String algorithm)
+                                       throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
+                                       FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException {
+
+               Preconditions.checkNotNull(ksTrustFile, "ksTrustFile cannot be null");
+               Preconditions.checkNotNull(ksKeysFile, "ksKeysFile cannot be null");
+
+               final char[] passphrase = pass.toCharArray();
+
+               // First initialize the key and trust material.
+               final KeyStore ksKeys = KeyStore.getInstance("JKS");
+               ksKeys.load(ksKeysFile, passphrase);
+               final KeyStore ksTrust = KeyStore.getInstance("JKS");
+               ksTrust.load(ksTrustFile, passphrase);
+
+               // KeyManager's decide which key material to use.
+               final KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
+               kmf.init(ksKeys, passphrase);
+
+               // TrustManager's decide whether to allow connections.
+               final TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
+               tmf.init(ksTrust);
+
+               final SSLContext sslContext = SSLContext.getInstance("TLS");
+
+               // Create/initialize the SSLContext with key material
+               sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+               return sslContext;
+       }
+
+}
diff --git a/util/src/main/java/org/opendaylight/protocol/util/TypesafeContainer.java b/util/src/main/java/org/opendaylight/protocol/util/TypesafeContainer.java
new file mode 100644 (file)
index 0000000..90671d5
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.util;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Container to store different types of objects and retrieve them back in
+ * a type-safe manner. this is a direct application of Joshua Bloch's typesafe
+ * heterogeneous container pattern from Effective Java.
+ *
+ * @param <S> Supertype of all objects stored in this container
+ */
+public class TypesafeContainer<S> implements Serializable {
+       private static final long serialVersionUID = 4369804407106485605L;
+       private final Map<Class<? extends S>, Object> entries;
+
+       /**
+        * Create a new container with default initial capacity
+        */
+       public TypesafeContainer() {
+               entries = new HashMap<Class<? extends S>, Object>();
+       }
+
+       /**
+        * Create a new container with specified initial capacity
+        *
+        * @param initialCapacity Desired initial capacity
+        */
+       public TypesafeContainer(final int initialCapacity) {
+               entries = new HashMap<Class<? extends S>, Object>(initialCapacity);
+       }
+
+       /**
+        * Get entry types currently present in the container.
+        *
+        * @return Entry types currently present in the contaier
+        */
+       public Set<Class<? extends S>> getEntryTypes() {
+               return entries.keySet();
+       }
+
+       /**
+        * Returns entry of a particular type
+        *
+        * @param clazz Entry type
+        * @return T Entry value, null if entry of specified type is not present
+        */
+       public <T extends S> T getEntry(final Class<T> clazz) {
+               return clazz.cast(entries.get(clazz));
+       }
+
+       /**
+        * Remove the entry for a particular type
+        *
+        * @param clazz Entry type, may not be null
+        */
+       public void removeEntry(final Class<? extends S> clazz) {
+               if (clazz == null) {
+                       throw new IllegalArgumentException("Entry type may not be null");
+               }
+               entries.remove(clazz);
+       }
+
+       /**
+        * Sets an entry of particular type
+        *
+        * @param clazz Entry type
+        * @param entry Entry value, may not be null
+        */
+       public void setEntry(final Class<? extends S> clazz, final S entry) {
+               if (clazz == null) {
+                       throw new IllegalArgumentException("Entry type may not be null");
+               }
+               if (entry == null) {
+                       throw new IllegalArgumentException("Entry value may not be null");
+               }
+
+               entries.put(clazz, entry);
+       }
+
+       @Override
+       public String toString(){
+               return addToStringAttributes(Objects.toStringHelper(this)).toString();
+       }
+
+       protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+               toStringHelper.add("entries", this.entries);
+               return toStringHelper;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (obj instanceof TypesafeContainer == false) {
+                       return false;
+               }
+               if (obj == this) {
+                       return true;
+               }
+               return entries.equals(((TypesafeContainer<?>)obj).entries);
+       }
+
+       @Override
+       public int hashCode() {
+               return entries.hashCode();
+       }
+
+}
+
diff --git a/util/src/site/apt/index.apt.vm b/util/src/site/apt/index.apt.vm
new file mode 100644 (file)
index 0000000..240ca24
--- /dev/null
@@ -0,0 +1,6 @@
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
diff --git a/util/src/site/site.xml b/util/src/site/site.xml
new file mode 100644 (file)
index 0000000..e468b3b
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+  <body>
+    <head>${project.artifactId}</head>
+    <links>
+      <item name="${project.artifactId}" href="index.html"/>
+    </links>
+
+    <menu ref="parent"/>
+
+    <menu ref="reports"/>
+
+    
+  </body>
+</project>
+
diff --git a/util/src/test/java/org/opendaylight/protocol/util/ByteArrayTest.java b/util/src/test/java/org/opendaylight/protocol/util/ByteArrayTest.java
new file mode 100644 (file)
index 0000000..54f1f63
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.util;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ByteArrayTest {
+
+       byte[] before = new byte[] { 15, 28, 4, 6, 9, 10 };
+
+       @Test
+       public void testBytesToFloat() {
+               final float expected = 8581;
+               final byte[] b = ByteArray.floatToBytes(expected);
+               assertEquals(expected, ByteArray.bytesToFloat(b), 50);
+       }
+
+       @Test
+       public void testSubByte() {
+               byte[] after = ByteArray.subByte(this.before, 0, 3);
+               byte[] expected = new byte[] { 15, 28, 4 };
+               assertArrayEquals(expected, after);
+               after = ByteArray.subByte(this.before, 5, 1);
+               expected = new byte[] { 10 };
+               assertArrayEquals(expected, after);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testSubByte2(){
+               ByteArray.subByte(new byte[0], 2, 2);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testSubByte3(){
+               ByteArray.subByte(this.before, 2, -1);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testSubByte4(){
+               ByteArray.subByte(this.before, -1, 2);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testSubByte5(){
+               ByteArray.subByte(this.before, 9, 2);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testSubByte6(){
+               ByteArray.subByte(this.before, 2, 19);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testSubByte7(){
+               ByteArray.subByte(this.before, 2, 7);
+       }
+
+       @Test
+       public void testCutBytes() {
+               byte[] after = ByteArray.cutBytes(this.before, 2);
+               byte[] expected = new byte[] { 4, 6, 9, 10 };
+               assertArrayEquals(expected, after);
+               after = ByteArray.cutBytes(this.before, 6);
+               expected = new byte[] {};
+               assertArrayEquals(expected, after);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testCutBytes2(){
+               ByteArray.cutBytes(new byte[0], 5);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testCutBytes3(){
+               ByteArray.cutBytes(this.before, 9);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testCutBytes4(){
+               ByteArray.cutBytes(this.before, 0);
+       }
+
+       @Test
+       public void testParseBits() {
+               final byte b = (byte) -76; // 1011 0100
+               final boolean[] after = ByteArray.parseBits(b);
+               assertTrue(after[0]);
+               assertFalse(after[1]);
+               assertTrue(after[2]);
+               assertTrue(after[3]);
+               assertFalse(after[4]);
+               assertTrue(after[5]);
+               assertFalse(after[6]);
+               assertFalse(after[7]);
+       }
+
+       private final byte[] inBytes = { (byte) 0x03, (byte) 0xFF, (byte) 0x01, (byte) 0x80 };
+       BitSet inBitSet = new BitSet();
+
+       @Before
+       public void generateBitSet() {
+               // 0x03
+               this.inBitSet.set(6, 8);
+
+               // 0xFF
+               this.inBitSet.set(8, 16);
+
+               // 0x01
+               this.inBitSet.set(23);
+
+               // 0x80
+               this.inBitSet.set(24);
+       }
+
+       @Test
+       public void testBytesToBitSetFunction() {
+               final BitSet iputBitSet = ByteArray.bytesToBitSet(this.inBytes);
+
+               assertEquals(this.inBitSet, iputBitSet);
+       }
+
+       @Test
+       public void testBitSetToBytesFunction() {
+               byte[] resultBytes = ByteArray.bitSetToBytes(this.inBitSet, this.inBytes.length);
+               assertArrayEquals(this.inBytes, resultBytes);
+
+               resultBytes = ByteArray.bitSetToBytes(this.inBitSet, this.inBytes.length - 1);
+               assertArrayEquals(Arrays.copyOf(this.inBytes, this.inBytes.length - 1), resultBytes);
+
+               resultBytes = ByteArray.bitSetToBytes(this.inBitSet, this.inBytes.length + 1);
+               assertArrayEquals(Arrays.copyOf(this.inBytes, this.inBytes.length + 1), resultBytes);
+       }
+
+       @Test
+       public void testFileToBytes() throws IOException {
+               final String FILE_TO_TEST = "src/test/resources/PCEStatefulCapabilityTlv1.bin";
+
+               final File fileToCompareWith = new File(FILE_TO_TEST);
+               final InputStream bytesIStream = new FileInputStream(fileToCompareWith);
+
+               try {
+                       final byte[] actualBytes = ByteArray.fileToBytes(FILE_TO_TEST);
+
+                       if (fileToCompareWith.length() > Integer.MAX_VALUE) {
+                               throw new IOException("Too large file to load in byte array.");
+                       }
+
+                       final byte[] expectedBytes = new byte[(int) fileToCompareWith.length()];
+
+                       int offset = 0;
+                       int numRead = 0;
+                       while (offset < expectedBytes.length && (numRead = bytesIStream.read(expectedBytes, offset, actualBytes.length - offset)) >= 0) {
+                               offset += numRead;
+                       }
+
+                       assertArrayEquals(expectedBytes, actualBytes);
+               } finally {
+                       bytesIStream.close();
+               }
+       }
+
+       @Test
+       public void testIntToBytes() {
+               assertEquals(Integer.MAX_VALUE, ByteArray.bytesToInt(ByteArray.intToBytes(Integer.MAX_VALUE)));
+               assertEquals(Integer.MIN_VALUE, ByteArray.bytesToInt(ByteArray.intToBytes(Integer.MIN_VALUE)));
+               assertEquals(5, ByteArray.bytesToInt(ByteArray.intToBytes(5)));
+       }
+
+       @Test
+       public void testLongToBytes_bytesToLong() {
+               assertEquals(Long.MAX_VALUE, ByteArray.bytesToLong(ByteArray.longToBytes(Long.MAX_VALUE)));
+               assertEquals(Long.MIN_VALUE, ByteArray.bytesToLong(ByteArray.longToBytes(Long.MIN_VALUE)));
+               assertEquals(5, ByteArray.bytesToLong(ByteArray.longToBytes(5)));
+       }
+
+       /**
+        * if less than 4 bytes are converted, zero bytes should be appendet at the
+        * buffer's start
+        */
+       @Test
+       public void testBytesToLong_prependingZeros() {
+               assertEquals(1, ByteArray.bytesToLong(new byte[] { 0, 0, 1 }));
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testBytesToInt(){
+               final byte[] b = new byte[Integer.SIZE + 1];
+               ByteArray.bytesToInt(b);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testBytesToShort2(){
+               final byte[] b = new byte[Short.SIZE + 1];
+               ByteArray.bytesToInt(b);
+       }
+
+       @Test
+       public void testBytes(){
+               assertTrue(ByteArray.bytesToInt(new byte[]{ 0, 0, 0, 15}) == 15);
+               assertEquals(Float.valueOf((float) 1.4E-45), Float.valueOf(ByteArray.bytesToFloat(new byte[]{ 0, 0, 0, 1})));
+               assertEquals(Long.valueOf(16613001005322L), Long.valueOf(ByteArray.bytesToLong(this.before)));
+               assertEquals(Short.valueOf((short) 1), Short.valueOf(ByteArray.bytesToShort(new byte[]{0, 1})));
+       }
+
+
+       @Test
+       public void testCopyBitRange() {
+               assertEquals((byte) 10, ByteArray.copyBitsRange((byte) 0x28, 2, 4));
+               assertEquals((byte) 3, ByteArray.copyBitsRange((byte) 0xFF, 2, 2));
+               assertEquals((byte) 7, ByteArray.copyBitsRange((byte) 0xFF, 5, 3));
+               assertEquals((byte) 15, ByteArray.copyBitsRange((byte) 0xFF, 0, 4));
+               assertEquals((byte) 31, ByteArray.copyBitsRange((byte) 0xF9, 0, 5));
+               assertEquals((byte) 0xA2, ByteArray.copyBitsRange((byte) 0xA2, 0, 8));
+               assertEquals((byte) 1, ByteArray.copyBitsRange((byte) 0xFF, 5, 1));
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testCopyBitsRange2(){
+               ByteArray.copyBitsRange((byte) 0x28, -1, 4);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testCopyBitsRange3(){
+               ByteArray.copyBitsRange((byte) 0x28, 1, 187);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testCopyBitsRange4(){
+               ByteArray.copyBitsRange((byte) 0x28, 1, 40);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testCopyBitsRange5(){
+               ByteArray.copyBitsRange((byte) 0x28, 28, 2);
+       }
+
+       @Test(expected = IllegalArgumentException.class)
+       public void testCopyBitsRange6(){
+               ByteArray.copyBitsRange((byte) 0x28, 2, -2);
+       }
+
+       @Test
+       public void testCopyWhole() {
+               final byte[] expecteds = { (byte) 0x04, (byte) 0x02, (byte) 0xD4, (byte) 0xf5, (byte) 0x32 };
+
+               final byte[] actuals = new byte[5];
+               actuals[0] = (byte) 0x04;
+               actuals[1] = (byte) 0x02;
+               actuals[2] = (byte) 0xD4;
+
+               final byte[] src = { (byte) 0xf5, (byte) 0x32 };
+
+               ByteArray.copyWhole(src, actuals, 3);
+
+               assertArrayEquals(expecteds, actuals);
+       }
+
+       @Test(expected = ArrayIndexOutOfBoundsException.class)
+       public void testCopyWhole2(){
+               ByteArray.copyWhole(new byte[0], new byte[1], 2);
+       }
+
+       @Test
+       public void testBytesToShort() {
+               final byte[] bytes1 = { (byte) 0x00, (byte) 0x01 };
+               final short expectedShort1 = 1;
+               assertEquals(expectedShort1, ByteArray.bytesToShort(bytes1));
+
+               final byte[] bytes2 = { (byte) 0xFF, (byte) 0xFF };
+               final short expectedShort2 = (short) 0xFFFF;
+               assertEquals(expectedShort2, ByteArray.bytesToShort(bytes2));
+
+               final byte[] bytes3 = { (byte) 0x25, (byte) 0x34 };
+               final short expectedShort3 = (short) 0x2534;
+               assertEquals(expectedShort3, ByteArray.bytesToShort(bytes3));
+       }
+
+       @Test
+       public void testShortToBytes() {
+               final byte[] expectedBytes1 = { (byte) 0x00, (byte) 0x01 };
+               assertArrayEquals(expectedBytes1, ByteArray.shortToBytes((short) 1));
+
+               final byte[] expectedBytes2 = { (byte) 0xFF, (byte) 0xFF };
+               assertArrayEquals(expectedBytes2, ByteArray.shortToBytes((short) 0xFFFF));
+
+               final byte[] expectedBytes3 = { (byte) 0x25, (byte) 0x34 };
+               assertArrayEquals(expectedBytes3, ByteArray.shortToBytes((short) 0x2534));
+       }
+
+       @Test
+       public void testFloatToBytes() {
+               final byte[] expectedBytes1 = { (byte) 0x35, (byte) 0x86, (byte) 0x37, (byte) 0xbd };
+               assertArrayEquals(expectedBytes1, ByteArray.floatToBytes((float) 0.000001));
+
+               final byte[] expectedBytes2 = { (byte) 0xEF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+               assertArrayEquals(expectedBytes2, ByteArray.floatToBytes((float) -158456315583795709447797473280.0));
+
+               final byte[] expectedBytes3 = { (byte) 0x49, (byte) 0xbf, (byte) 0x1c, (byte) 0x92 };
+               assertArrayEquals(expectedBytes3, ByteArray.floatToBytes((float) 1565586.253637));
+       }
+
+       @Test
+       public void testBytesToHexString() {
+               final byte[] b = new byte[] { 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, };
+               final String expected = "01 16 01 16 01 16 01 16  01 16 01 16 01 16 01 16\n01 16 ";
+               assertEquals(expected, ByteArray.bytesToHexString(b));
+       }
+
+       @Test
+       public void testBytesToHRString() {
+               byte[] b;
+
+               // test valid US-ASCII string
+               b = new byte[] { (byte) 79, (byte) 102, (byte) 45, (byte) 57, (byte) 107, (byte) 45, (byte) 48, (byte) 50 };
+               final String expected = "Of-9k-02";
+               assertEquals(expected, ByteArray.bytesToHRString(b));
+
+               // test Utf-8 restricted bytes
+               b = new byte[] { (byte) 246, (byte) 248, (byte) 254 };
+               assertEquals(Arrays.toString(b), ByteArray.bytesToHRString(b));
+
+               // test unexpected continuation bytes
+               b = new byte[] { (byte) 128, (byte) 113, (byte) 98 };
+               assertEquals(Arrays.toString(b), ByteArray.bytesToHRString(b));
+       }
+
+       @Test
+       public void testFindByteSequence() {
+               final byte[] bytes = new byte[] { (byte)36, (byte)41, (byte)55, (byte)101, (byte)38 };
+               final byte[] sequence1 = new byte[] { (byte)36, (byte)41 };
+
+               assertEquals(0, ByteArray.findByteSequence(bytes, sequence1));
+
+               final byte[] sequence2 = new byte[] { (byte)55, (byte)38 };
+
+               assertEquals(-1, ByteArray.findByteSequence(bytes, sequence2));
+
+               final byte[] sequence3 = new byte[] { (byte)101, (byte)38 };
+
+               assertEquals(3, ByteArray.findByteSequence(bytes, sequence3));
+
+               try {
+                       ByteArray.findByteSequence(bytes, new byte[]  { (byte)36, (byte)41, (byte)55, (byte)101, (byte)38, (byte)66 });
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Sequence to be found is longer than the given byte array.", e.getMessage());
+               }
+       }
+
+       @Test
+       public void testMaskBytes() {
+               final byte[] bytes = new byte[] {(byte)0xAC, (byte)0xA8, (byte)0x1F, (byte)0x08 };
+               try {
+                       ByteArray.maskBytes(bytes, 48);
+               } catch (final IllegalArgumentException e) {
+                       assertEquals("Attempted to apply invalid mask (too long)", e.getMessage());
+               }
+
+               assertArrayEquals(bytes, ByteArray.maskBytes(bytes, 32));
+
+               assertArrayEquals(new byte[] { (byte)0xAC, (byte)0x80, 0, 0}, ByteArray.maskBytes(bytes, 10));
+       }
+
+}
diff --git a/util/src/test/resources/PCEStatefulCapabilityTlv1.bin b/util/src/test/resources/PCEStatefulCapabilityTlv1.bin
new file mode 100644 (file)
index 0000000..ae47c97
Binary files /dev/null and b/util/src/test/resources/PCEStatefulCapabilityTlv1.bin differ