/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package org.onosproject.bgp.controller.impl;

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.onosproject.bgp.controller.BgpController;
import org.onosproject.bgp.controller.BgpId;
import org.onosproject.bgp.controller.BgpLocalRib;
import org.onosproject.bgp.controller.BgpNodeListener;
import org.onosproject.bgp.controller.BgpSessionInfo;
import org.onosproject.bgpio.protocol.BgpLSNlri;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpPrefixLSIdentifier;
import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib;
import org.onosproject.bgpio.types.RouteDistinguisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.MoreObjects;

/**
 * Implementation of local RIB.
 */
public class BgpLocalRibImpl implements BgpLocalRib {

    private static final Logger log = LoggerFactory.getLogger(BgpLocalRibImpl.class);
    private BgpController bgpController;

    private Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib> nodeTree = new TreeMap<>();
    private Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib> linkTree = new TreeMap<>();
    private Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib> prefixTree = new TreeMap<>();

    private Map<RouteDistinguisher, Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnNodeTree
                                                                                                   = new TreeMap<>();
    private Map<RouteDistinguisher, Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnLinkTree
                                                                                                   = new TreeMap<>();
    private Map<RouteDistinguisher, Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnPrefixTree
                                                                                                   = new TreeMap<>();

    public BgpLocalRibImpl(BgpController bgpController) {
        this.bgpController = bgpController;
    }

    /**
     * Gets node NLRI tree.
     *
     * @return node tree
     */
    public Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib> nodeTree() {
        return nodeTree;
    }

    /**
     * Gets link NLRI tree.
     *
     * @return link tree
     */
    public Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib> linkTree() {
        return linkTree;
    }

    /**
     * Gets prefix NLRI tree.
     *
     * @return prefix tree
     */
    public Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib> prefixTree() {
        return prefixTree;
    }

    /**
     * Gets VPN node NLRI tree.
     *
     * @return vpn node NLRI tree
     */
    public Map<RouteDistinguisher, Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnNodeTree() {
        return vpnNodeTree;
    }

    /**
     * Gets VPN link NLRI tree.
     *
     * @return vpn link NLRI Tree
     */
    public Map<RouteDistinguisher, Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnLinkTree() {
        return vpnLinkTree;
    }

    /**
     * Gets VPN prefix NLRI tree.
     *
     * @return vpn prefix NLRI Tree
     */
    public Map<RouteDistinguisher, Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnPrefixTree() {
        return vpnPrefixTree;
    }

    @Override
    public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details) {
        int decisionResult;

        log.debug("Add to local RIB {}", details.toString());

        PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
                                                               sessionInfo.remoteBgpId().ipAddress(),
                                                               sessionInfo.remoteBgpIdentifier(),
                                                               sessionInfo.remoteBgpASNum(),
                                                               sessionInfo.isIbgpSession(), details);
        if (nlri instanceof BgpNodeLSNlriVer4) {
            BgpNodeLSIdentifier nodeLsIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors();
            if (nodeTree.containsKey(nodeLsIdentifier)) {
                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
                // Compare local RIB entry with the current attribute
                decisionResult = selectionAlgo.compare(nodeTree.get(nodeLsIdentifier), detailsLocRib);
                if (decisionResult < 0) {
                    nodeTree.replace(nodeLsIdentifier, detailsLocRib);
                    log.debug("Local RIB update node: {}", detailsLocRib.toString());
                }
            } else {
                nodeTree.put(nodeLsIdentifier, detailsLocRib);
                for (BgpNodeListener l : bgpController.listener()) {
                    l.addNode((BgpNodeLSNlriVer4) nlri);
                }
                log.debug("Local RIB ad node: {}", detailsLocRib.toString());
            }
        } else if (nlri instanceof BgpLinkLsNlriVer4) {
            BgpLinkLSIdentifier linkLsIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier();
            if (linkTree.containsKey(linkLsIdentifier)) {
                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
                // Compare local RIB entry with the current attribute
                decisionResult = selectionAlgo.compare(linkTree.get(linkLsIdentifier), detailsLocRib);
                if (decisionResult < 0) {
                    linkTree.replace(linkLsIdentifier, detailsLocRib);
                    log.debug("Local RIB update link: {}", detailsLocRib.toString());
                }
            } else {
                linkTree.put(linkLsIdentifier, detailsLocRib);
                log.debug("Local RIB add link: {}", detailsLocRib.toString());
            }
        } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
            BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier();
            if (prefixTree.containsKey(prefixIdentifier)) {
                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
                // Compare local RIB entry with the current attribute
                decisionResult = selectionAlgo.compare(prefixTree.get(prefixIdentifier), detailsLocRib);
                if (decisionResult < 0) {
                    prefixTree.replace(prefixIdentifier, detailsLocRib);
                    log.debug("Local RIB update prefix: {}", detailsLocRib.toString());
                }
            } else {
                prefixTree.put(prefixIdentifier, detailsLocRib);
                log.debug("Local RIB add prefix: {}", detailsLocRib.toString());
            }
        }
    }

    @Override
    public void delete(BgpLSNlri nlri) {
        log.debug("Delete from local RIB.");

        // Update local RIB
        decisionProcess(nlri);
    }

    /**
     * Update local RIB based on selection algorithm.
     *
     * @param nlri NLRI to update
     */
    public void decisionProcess(BgpLSNlri nlri) {
        checkNotNull(nlri);
        if (nlri instanceof BgpNodeLSNlriVer4) {
            selectionProcessNode(nlri, false);
        } else if (nlri instanceof BgpLinkLsNlriVer4) {
            selectionProcessLink(nlri, false);
        } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
            selectionProcessPrefix(nlri, false);
        }
    }

    /**
     * Update VPN local RIB .
     *
     * @param nlri NLRI to update
     * @param routeDistinguisher VPN id to update
     */
    public void decisionProcess(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) {
        checkNotNull(nlri);
        if (nlri instanceof BgpNodeLSNlriVer4) {
            if (vpnNodeTree.containsKey(routeDistinguisher)) {
                selectionProcessNode(nlri, true);
                if (nodeTree.size() == 0) {
                    vpnNodeTree.remove(routeDistinguisher);
                }
            }
        } else if (nlri instanceof BgpLinkLsNlriVer4) {
            if (vpnLinkTree.containsKey(routeDistinguisher)) {
                selectionProcessLink(nlri, true);
                if (linkTree.size() == 0) {
                    vpnLinkTree.remove(routeDistinguisher);
                }
            }
        } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
            if (vpnPrefixTree.containsKey(routeDistinguisher)) {
                selectionProcessPrefix(nlri, true);
                if (prefixTree.size() == 0) {
                    vpnPrefixTree.remove(routeDistinguisher);
                }
            }
        }
    }

     /**
     * Selection process for local RIB node.
     *
     * @param nlri NLRI to update
     * @param isVpnRib true if VPN  local RIB, otherwise false
     */
    public void selectionProcessNode(BgpLSNlri nlri, boolean isVpnRib) {
        BgpPeerImpl peer;
        BgpSessionInfo sessionInfo;
        int decisionResult;
        boolean containsKey;

        BgpNodeLSIdentifier nodeLsIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors();

        if (nodeTree.containsKey(nodeLsIdentifier)) {
            for (BgpNodeListener l : bgpController.listener()) {
                l.deleteNode((BgpNodeLSNlriVer4) nlri);
            }
            log.debug("Local RIB delete node: {}", nodeLsIdentifier.toString());
            nodeTree.remove(nodeLsIdentifier);
        }

        for (BgpId bgpId : bgpController.connectedPeers().keySet()) {
            peer = (BgpPeerImpl) (bgpController.getPeer(bgpId));

            if (nodeTree.containsKey(nodeLsIdentifier)) {
                containsKey = (!isVpnRib) ? (peer.adjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) :
                                            (peer.vpnAdjacencyRib().nodeTree().containsKey(nodeLsIdentifier));

                if (!containsKey) {
                    continue;
                }
                sessionInfo = peer.sessionInfo();
                PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
                                                                sessionInfo.remoteBgpId().ipAddress(),
                                                                sessionInfo.remoteBgpIdentifier(),
                                                                sessionInfo.remoteBgpASNum(),
                                                                sessionInfo.isIbgpSession(),
                                                                (!isVpnRib) ?
                                                                (peer.adjacencyRib().nodeTree()
                                                                                    .get(nodeLsIdentifier)) :
                                                                (peer.vpnAdjacencyRib().nodeTree()
                                                                                        .get(nodeLsIdentifier)));
                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
                decisionResult = selectionAlgo.compare(nodeTree.get(nodeLsIdentifier), detailsLocRib);
                if (decisionResult < 0) {
                    nodeTree.replace(nodeLsIdentifier, detailsLocRib);
                    log.debug("Local RIB node updated: {}", detailsLocRib.toString());
                }
            } else {
                if (!isVpnRib) {
                    if (peer.adjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) {
                        add(peer.sessionInfo(), nlri, peer.adjacencyRib().nodeTree().get(nodeLsIdentifier));
                    }
                } else {
                    if (peer.vpnAdjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) {
                        add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().nodeTree().get(nodeLsIdentifier));
                    }
                }
            }
        }
    }

     /**
     * Selection process for local RIB link.
     *
     * @param nlri NLRI to update
     * @param isVpnRib true if VPN local RIB, otherwise false
     */
    public void selectionProcessLink(BgpLSNlri nlri, boolean isVpnRib) {
        BgpPeerImpl peer;
        BgpSessionInfo sessionInfo;
        int decisionResult;
        boolean containsKey;

        BgpLinkLSIdentifier linkLsIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier();

        if (linkTree.containsKey(linkLsIdentifier)) {
            log.debug("Local RIB remove link: {}", linkLsIdentifier.toString());
            linkTree.remove(linkLsIdentifier);
        }

        for (BgpId bgpId : bgpController.connectedPeers().keySet()) {
            peer = (BgpPeerImpl) (bgpController.getPeer(bgpId));

            if (linkTree.containsKey(linkLsIdentifier)) {

                containsKey = (!isVpnRib) ? (peer.adjacencyRib().linkTree().containsKey(linkLsIdentifier)) :
                                            (peer.vpnAdjacencyRib().linkTree().containsKey(linkLsIdentifier));

                if (!containsKey) {
                    continue;
                }

                sessionInfo = peer.sessionInfo();

                PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
                                                            sessionInfo.remoteBgpId().ipAddress(),
                                                            sessionInfo.remoteBgpIdentifier(),
                                                            sessionInfo.remoteBgpASNum(),
                                                            sessionInfo.isIbgpSession(),
                                                            ((!isVpnRib) ?
                                                            (peer.adjacencyRib().linkTree().get(linkLsIdentifier)) :
                                                            (peer.vpnAdjacencyRib().linkTree()
                                                                                   .get(linkLsIdentifier))));

                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
                decisionResult = selectionAlgo.compare(linkTree.get(linkLsIdentifier), detailsLocRib);
                if (decisionResult < 0) {
                    linkTree.replace(linkLsIdentifier, detailsLocRib);
                    log.debug("Local RIB link updated: {}", detailsLocRib.toString());
                }
            } else {
                if (!isVpnRib) {
                    if (peer.adjacencyRib().linkTree().containsKey(linkLsIdentifier)) {
                        add(peer.sessionInfo(), nlri, peer.adjacencyRib().linkTree().get(linkLsIdentifier));
                    }
                } else {
                    if (peer.vpnAdjacencyRib().linkTree().containsKey(linkLsIdentifier)) {
                        add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().linkTree().get(linkLsIdentifier));
                    }
                }
            }
        }
    }

     /**
     * Selection process for local RIB prefix.
     *
     * @param nlri NLRI to update
     * @param isVpnRib true if VPN local RIB, otherwise false
     */
    public void selectionProcessPrefix(BgpLSNlri nlri, boolean isVpnRib) {
        BgpPeerImpl peer;
        BgpSessionInfo sessionInfo;
        int decisionResult;
        boolean containsKey;

        BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier();
        if (prefixTree.containsKey(prefixIdentifier)) {
            log.debug("Local RIB remove prefix: {}", prefixIdentifier.toString());
            prefixTree.remove(prefixIdentifier);
        }

        for (BgpId bgpId : bgpController.connectedPeers().keySet()) {
            peer = (BgpPeerImpl) (bgpController.getPeer(bgpId));

            if (prefixTree.containsKey(prefixIdentifier)) {

                containsKey = (!isVpnRib) ? (peer.adjacencyRib().prefixTree().containsKey(prefixIdentifier)) :
                                            (peer.vpnAdjacencyRib().prefixTree().containsKey(prefixIdentifier));
                if (!containsKey) {
                    continue;
                }
                sessionInfo = peer.sessionInfo();

                PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
                                                                sessionInfo.remoteBgpId().ipAddress(),
                                                                sessionInfo.remoteBgpIdentifier(),
                                                                sessionInfo.remoteBgpASNum(),
                                                                sessionInfo.isIbgpSession(),
                                                                ((!isVpnRib) ?
                                                                (peer.adjacencyRib().prefixTree()
                                                                                    .get(prefixIdentifier)) :
                                                                (peer.vpnAdjacencyRib().prefixTree()
                                                                                       .get(prefixIdentifier))));

                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
                decisionResult = selectionAlgo.compare(prefixTree.get(prefixIdentifier), detailsLocRib);
                if (decisionResult < 0) {
                    prefixTree.replace(prefixIdentifier, detailsLocRib);
                    log.debug("local RIB prefix updated: {}", detailsLocRib.toString());
                }
            } else {
                    if (!isVpnRib) {
                        if (peer.adjacencyRib().prefixTree().containsKey(prefixIdentifier)) {
                            add(peer.sessionInfo(), nlri, peer.adjacencyRib().prefixTree().get(prefixIdentifier));
                    } else {
                        if (peer.vpnAdjacencyRib().prefixTree().containsKey(prefixIdentifier)) {
                            add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().prefixTree().get(prefixIdentifier));
                        }
                    }
                }
            }
        }
    }

    @Override
    public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details,
                    RouteDistinguisher routeDistinguisher) {
        add(sessionInfo, nlri, details);
        if (nlri instanceof BgpNodeLSNlriVer4) {
            if (!vpnNodeTree.containsKey(routeDistinguisher)) {
                vpnNodeTree.put(routeDistinguisher, nodeTree);
            }
        } else if (nlri instanceof BgpLinkLsNlriVer4) {
            if (!vpnLinkTree.containsKey(routeDistinguisher)) {
                vpnLinkTree.put(routeDistinguisher, linkTree);
            }
        } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
            if (!vpnPrefixTree.containsKey(routeDistinguisher)) {
                vpnPrefixTree.put(routeDistinguisher, prefixTree);
            }
        }
    }

    @Override
    public void delete(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) {
        // Update local RIB
        decisionProcess(nlri, routeDistinguisher);
    }

    /**
     * Update local RIB node based on avaliable peer adjacency RIB.
     *
     * @param o adjacency-in/VPN adjacency-in
     */
    public void localRIBUpdateNode(Object o) {

        if (o instanceof AdjRibIn) {
            AdjRibIn adjRib = (AdjRibIn) o;
            log.debug("Update local RIB node.");

            Set<BgpNodeLSIdentifier> nodeKeys = adjRib.nodeTree().keySet();
            for (BgpNodeLSIdentifier key : nodeKeys) {
                PathAttrNlriDetails pathAttrNlri = adjRib.nodeTree().get(key);

                BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(pathAttrNlri.identifier(), pathAttrNlri
                                                                   .protocolID().getType(), key, false, null);
                decisionProcess(nodeNlri);
            }
        }

        if (o instanceof VpnAdjRibIn) {
            VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o;
            log.debug("Update local RIB VPN node.");
            Set<RouteDistinguisher> nodeKeysVpn = vpnAdjRib.vpnNodeTree().keySet();
            Map<BgpNodeLSIdentifier, PathAttrNlriDetails> node;
            for (RouteDistinguisher keyVpnNode : nodeKeysVpn) {
                node = vpnAdjRib.vpnNodeTree().get(keyVpnNode);

                Set<BgpNodeLSIdentifier> vpnNodeKeys = node.keySet();
                for (BgpNodeLSIdentifier key : vpnNodeKeys) {
                    PathAttrNlriDetails pathAttrNlri = vpnAdjRib.nodeTree().get(key);
                    BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(pathAttrNlri.identifier(),
                                                                      pathAttrNlri.protocolID().getType(),
                                                                      key, true, keyVpnNode);
                    decisionProcess(nodeNlri, keyVpnNode);
                }
            }
        }
    }

    /**
     * Update localRIB link based on avaliable peer adjacency RIB.
     *
     * @param o adjacency-in/VPN adjacency-in
     */
    public void localRIBUpdateLink(Object o) {

        if (o instanceof AdjRibIn) {
            AdjRibIn adjRib = (AdjRibIn) o;
            log.debug("Update local RIB link.");

            Set<BgpLinkLSIdentifier> linkKeys = adjRib.linkTree().keySet();
            for (BgpLinkLSIdentifier key : linkKeys) {
                PathAttrNlriDetails pathAttrNlri = adjRib.linkTree().get(key);
                BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4(pathAttrNlri.protocolID().getType(),
                                                                   pathAttrNlri.identifier(), key, null, false);
                decisionProcess(linkNlri);
            }
        }

        if (o instanceof VpnAdjRibIn) {
            VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o;
            log.debug("Update local RIB VPN link");

            Set<RouteDistinguisher> linkKeysVpn = vpnAdjRib.vpnLinkTree().keySet();
            Map<BgpLinkLSIdentifier, PathAttrNlriDetails> link;
            for (RouteDistinguisher keyVpnLink : linkKeysVpn) {
                link = vpnAdjRib.vpnLinkTree().get(keyVpnLink);

                Set<BgpLinkLSIdentifier> vpnLinkKeys = link.keySet();
                for (BgpLinkLSIdentifier key : vpnLinkKeys) {
                    PathAttrNlriDetails pathAttrNlri = vpnAdjRib.linkTree().get(key);
                    BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4(pathAttrNlri.protocolID().getType(),
                                                                       pathAttrNlri.identifier(), key, keyVpnLink,
                                                                       true);
                    decisionProcess(linkNlri, keyVpnLink);
                }
            }
        }
    }

    /**
     * Update localRIB prefix based on avaliable peer adjacency RIB.
     *
     * @param o instance of adjacency-in/VPN adjacency-in
     */
    public void localRIBUpdatePrefix(Object o) {

        if (o instanceof AdjRibIn) {
            AdjRibIn adjRib = (AdjRibIn) o;
            log.debug("Update local RIB prefix.");

            Set<BgpPrefixLSIdentifier> prefixKeys = adjRib.prefixTree().keySet();
            for (BgpPrefixLSIdentifier key : prefixKeys) {
                PathAttrNlriDetails pathAttrNlri = adjRib.prefixTree().get(key);
                BgpPrefixIPv4LSNlriVer4 prefixNlri = new BgpPrefixIPv4LSNlriVer4(
                                                                             pathAttrNlri.identifier(),
                                                                             pathAttrNlri.protocolID().getType(),
                                                                             key, null, false);
                decisionProcess(prefixNlri);
            }
        }

        if (o instanceof VpnAdjRibIn) {
            VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o;
            log.debug("Update local RIB VPN prefix.");

            Set<RouteDistinguisher> prefixKeysVpn = vpnAdjRib.vpnPrefixTree().keySet();
            Map<BgpPrefixLSIdentifier, PathAttrNlriDetails> prefix;
            for (RouteDistinguisher keyVpnPrefix : prefixKeysVpn) {
                prefix = vpnAdjRib.vpnPrefixTree().get(keyVpnPrefix);

                Set<BgpPrefixLSIdentifier> vpnPrefixKeys = prefix.keySet();
                for (BgpPrefixLSIdentifier key : vpnPrefixKeys) {
                    PathAttrNlriDetails pathAttrNlri = vpnAdjRib.prefixTree().get(key);
                    BgpPrefixIPv4LSNlriVer4 prefixNlri = new BgpPrefixIPv4LSNlriVer4(pathAttrNlri.identifier(),
                                                                                     pathAttrNlri.protocolID()
                                                                                             .getType(), key,
                                                                                     keyVpnPrefix, true);
                    decisionProcess(prefixNlri, keyVpnPrefix);
                }
            }
        }
    }

    /**
     * Update localRIB.
     *
     * @param adjRibIn adjacency RIB-in
     */
    public void localRIBUpdate(AdjRibIn adjRibIn) {
        log.debug("Update local RIB.");

        localRIBUpdateNode(adjRibIn);
        localRIBUpdateLink(adjRibIn);
        localRIBUpdatePrefix(adjRibIn);
    }

    /**
     * Update localRIB.
     *
     * @param vpnAdjRibIn VPN adjacency RIB-in
     */
    public void localRIBUpdate(VpnAdjRibIn vpnAdjRibIn) {
        log.debug("Update VPN local RIB.");

        localRIBUpdateNode(vpnAdjRibIn);
        localRIBUpdateLink(vpnAdjRibIn);
        localRIBUpdatePrefix(vpnAdjRibIn);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass()).omitNullValues().add("nodeTree", nodeTree)
                .add("linkTree", linkTree).add("prefixTree", prefixTree).add("vpnNodeTree", vpnNodeTree)
                .add("vpnLinkTree", vpnLinkTree).add("vpnPrefixTree", vpnPrefixTree).toString();
    }
}
