#include<string>
#include<utility>
#include "nlsr_lsdb.hpp"
#include "nlsr.hpp"

namespace nlsr
{

    using namespace std;

    void
    Lsdb::cancelScheduleLsaExpiringEvent(Nlsr& pnlsr, EventId eid)
    {
        pnlsr.getScheduler().cancelEvent(eid);
    }

    static bool
    nameLsaCompareByKey(NameLsa& nlsa1, string& key)
    {
        return nlsa1.getNameLsaKey()==key;
    }


    bool
    Lsdb::buildAndInstallOwnNameLsa(Nlsr& pnlsr)
    {
        NameLsa nameLsa(pnlsr.getConfParameter().getRouterPrefix()
                        , 1
                        , pnlsr.getSm().getNameLsaSeq()+1
                        , pnlsr.getConfParameter().getRouterDeadInterval()
                        , pnlsr.getNpl() );
        pnlsr.getSm().setNameLsaSeq(pnlsr.getSm().getNameLsaSeq()+1);
        return installNameLsa(pnlsr,nameLsa);
    }

    std::pair<NameLsa&, bool>
    Lsdb::getNameLsa(string key)
    {
        std::list<NameLsa >::iterator it = std::find_if( nameLsdb.begin(),
                                           nameLsdb.end(),
                                           bind(nameLsaCompareByKey, _1, key));
        if( it != nameLsdb.end())
        {
            return std::make_pair(boost::ref((*it)),true);
        }
        NameLsa nlsa;
        return std::make_pair(boost::ref(nlsa),false);
    }


    ndn::EventId
    Lsdb::scheduleNameLsaExpiration(Nlsr& pnlsr, string key, int seqNo, int expTime)
    {
        return pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(expTime),
                ndn::bind(&Lsdb::exprireOrRefreshNameLsa,
                          this,boost::ref(pnlsr), key, seqNo));
    }

    bool
    Lsdb::installNameLsa(Nlsr& pnlsr, NameLsa &nlsa)
    {
        int timeToExpire=lsaRefreshTime;
        std::pair<NameLsa& , bool> chkNameLsa=getNameLsa(nlsa.getNameLsaKey());
        if ( !chkNameLsa.second )
        {
            addNameLsa(nlsa);
            printNameLsdb();
            if ( nlsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
            {
                pnlsr.getNpt().addNpte(nlsa.getOrigRouter(),nlsa.getOrigRouter(),pnlsr);
                std::list<string> nameList=nlsa.getNpl().getNameList();
                for(std::list<string>::iterator it=nameList.begin(); it!=nameList.end(); it++)
                {
                    if ( (*it) !=pnlsr.getConfParameter().getRouterPrefix())
                    {
                        pnlsr.getNpt().addNpte((*it),nlsa.getOrigRouter(),pnlsr);
                    }
                }
            }
            if(nlsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
            {
                timeToExpire=nlsa.getLifeTime();
            }
            nlsa.setLsaExpiringEventId(scheduleNameLsaExpiration( pnlsr,
                                       nlsa.getNameLsaKey(), nlsa.getLsSeqNo(), timeToExpire));
        }
        else
        {
            if ( chkNameLsa.first.getLsSeqNo() < nlsa.getLsSeqNo() )
            {
                chkNameLsa.first.setLsSeqNo(nlsa.getLsSeqNo());
                chkNameLsa.first.setLifeTime(nlsa.getLifeTime());
                chkNameLsa.first.getNpl().sortNpl();
                nlsa.getNpl().sortNpl();
                std::list<string> nameToAdd;
                std::set_difference(nlsa.getNpl().getNameList().begin(),
                                    nlsa.getNpl().getNameList().end(),
                                    chkNameLsa.first.getNpl().getNameList().begin(),
                                    chkNameLsa.first.getNpl().getNameList().end(),
                                    std::inserter(nameToAdd, nameToAdd.begin()));
                for(std::list<string>::iterator it=nameToAdd.begin(); it!=nameToAdd.end();
                        ++it)
                {
                    chkNameLsa.first.addNameToLsa((*it));
                    if ( nlsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
                    {
                        if ( (*it) !=pnlsr.getConfParameter().getRouterPrefix())
                        {
                            pnlsr.getNpt().addNpte((*it),nlsa.getOrigRouter(),pnlsr);
                        }
                    }
                }
                std::list<string> nameToRemove;
                std::set_difference(chkNameLsa.first.getNpl().getNameList().begin(),
                                    chkNameLsa.first.getNpl().getNameList().end(),
                                    nlsa.getNpl().getNameList().begin(),
                                    nlsa.getNpl().getNameList().end(),
                                    std::inserter(nameToRemove, nameToRemove.begin()));
                for(std::list<string>::iterator it=nameToRemove.begin();
                        it!=nameToRemove.end(); ++it)
                {
                    chkNameLsa.first.removeNameFromLsa((*it));
                    if ( nlsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
                    {
                        if ( (*it) !=pnlsr.getConfParameter().getRouterPrefix())
                        {
                            pnlsr.getNpt().removeNpte((*it),nlsa.getOrigRouter(),pnlsr);
                        }
                    }
                }
                if(nlsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
                {
                    timeToExpire=nlsa.getLifeTime();
                }
                cancelScheduleLsaExpiringEvent(pnlsr,
                                               chkNameLsa.first.getLsaExpiringEventId());
                chkNameLsa.first.setLsaExpiringEventId(scheduleNameLsaExpiration( pnlsr,
                                                       nlsa.getNameLsaKey(), nlsa.getLsSeqNo(), timeToExpire));
            }
        }
        return true;
    }

    bool
    Lsdb::addNameLsa(NameLsa &nlsa)
    {
        std::list<NameLsa >::iterator it = std::find_if( nameLsdb.begin(),
                                           nameLsdb.end(), bind(nameLsaCompareByKey, _1, nlsa.getNameLsaKey()));
        if( it == nameLsdb.end())
        {
            nameLsdb.push_back(nlsa);
            return true;
        }
        return false;
    }

    bool
    Lsdb::removeNameLsa(Nlsr& pnlsr, string& key)
    {
        std::list<NameLsa >::iterator it = std::find_if( nameLsdb.begin(),
                                           nameLsdb.end(),
                                           bind(nameLsaCompareByKey, _1, key));
        if ( it != nameLsdb.end() )
        {
            if ( (*it).getOrigRouter() != pnlsr.getConfParameter().getRouterPrefix()  )
            {
                pnlsr.getNpt().removeNpte((*it).getOrigRouter(),(*it).getOrigRouter(),pnlsr);
                for( std::list<string>::iterator nit=(*it).getNpl().getNameList().begin();
                        nit!=(*it).getNpl().getNameList().end(); ++nit)
                {
                    if ( (*nit) !=pnlsr.getConfParameter().getRouterPrefix())
                    {
                        pnlsr.getNpt().removeNpte((*nit),(*it).getOrigRouter(),pnlsr);
                    }
                }
            }
            nameLsdb.erase(it);
            return true;
        }
        return false;
    }

    bool
    Lsdb::doesNameLsaExist(string key)
    {
        std::list<NameLsa >::iterator it = std::find_if( nameLsdb.begin(),
                                           nameLsdb.end(),
                                           bind(nameLsaCompareByKey, _1, key));
        if( it == nameLsdb.end())
        {
            return false;
        }
        return true;
    }

    void
    Lsdb::printNameLsdb()
    {
        cout<<"---------------Name LSDB-------------------"<<endl;
        for( std::list<NameLsa>::iterator it=nameLsdb.begin();
                it!= nameLsdb.end() ; it++)
        {
            cout<< (*it) <<endl;
        }
    }

// Cor LSA and LSDB related Functions start here


    static bool
    corLsaCompareByKey(CorLsa& clsa, string& key)
    {
        return clsa.getCorLsaKey()==key;
    }

    bool
    Lsdb::buildAndInstallOwnCorLsa(Nlsr& pnlsr)
    {
        CorLsa corLsa(pnlsr.getConfParameter().getRouterPrefix()
                      , 3
                      , pnlsr.getSm().getCorLsaSeq()+1
                      , pnlsr.getConfParameter().getRouterDeadInterval()
                      , pnlsr.getConfParameter().getCorR()
                      , pnlsr.getConfParameter().getCorTheta() );
        pnlsr.getSm().setCorLsaSeq(pnlsr.getSm().getCorLsaSeq()+1);
        installCorLsa(pnlsr, corLsa);
        return true;
    }

    std::pair<CorLsa&, bool>
    Lsdb::getCorLsa(string key)
    {
        std::list< CorLsa >::iterator it = std::find_if( corLsdb.begin(),
                                           corLsdb.end(),
                                           bind(corLsaCompareByKey, _1, key));
        if( it != corLsdb.end())
        {
            return std::make_pair(boost::ref((*it)), true);
        }
        CorLsa clsa;
        return std::make_pair(boost::ref(clsa),false);
    }

    ndn::EventId
    Lsdb::scheduleCorLsaExpiration(Nlsr& pnlsr, string key, int seqNo, int expTime)
    {
        return pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(expTime),
                ndn::bind(&Lsdb::exprireOrRefreshCorLsa,
                          this,boost::ref(pnlsr),key,seqNo));
    }

    bool
    Lsdb::installCorLsa(Nlsr& pnlsr, CorLsa &clsa)
    {
        int timeToExpire=lsaRefreshTime;
        std::pair<CorLsa& , bool> chkCorLsa=getCorLsa(clsa.getCorLsaKey());
        if ( !chkCorLsa.second )
        {
            addCorLsa(clsa);
            printCorLsdb(); //debugging purpose
            if ( clsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
            {
                pnlsr.getNpt().addNpte(clsa.getOrigRouter(),clsa.getOrigRouter(),pnlsr);
            }
            if (pnlsr.getConfParameter().getIsHyperbolicCalc() >=1 )
            {
                pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);
            }
            if(clsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
            {
                timeToExpire=clsa.getLifeTime();
            }
            scheduleCorLsaExpiration(pnlsr,clsa.getCorLsaKey(),
                                     clsa.getLsSeqNo(), timeToExpire);
        }
        else
        {
            if ( chkCorLsa.first.getLsSeqNo() < clsa.getLsSeqNo() )
            {
                chkCorLsa.first.setLsSeqNo(clsa.getLsSeqNo());
                chkCorLsa.first.setLifeTime(clsa.getLifeTime());
                if ( !chkCorLsa.first.isLsaContentEqual(clsa) )
                {
                    chkCorLsa.first.setCorRadius(clsa.getCorRadius());
                    chkCorLsa.first.setCorTheta(clsa.getCorTheta());
                    if (pnlsr.getConfParameter().getIsHyperbolicCalc() >=1 )
                    {
                        pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);
                    }
                }
                if(clsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
                {
                    timeToExpire=clsa.getLifeTime();
                }
                cancelScheduleLsaExpiringEvent(pnlsr,
                                               chkCorLsa.first.getLsaExpiringEventId());
                chkCorLsa.first.setLsaExpiringEventId(scheduleCorLsaExpiration(pnlsr,
                                                      clsa.getCorLsaKey(),
                                                      clsa.getLsSeqNo(), timeToExpire));
            }
        }
        return true;
    }

    bool
    Lsdb::addCorLsa(CorLsa& clsa)
    {
        std::list<CorLsa >::iterator it = std::find_if( corLsdb.begin(),
                                          corLsdb.end(),
                                          bind(corLsaCompareByKey, _1, clsa.getCorLsaKey()));
        if( it == corLsdb.end())
        {
            corLsdb.push_back(clsa);
            return true;
        }
        return false;
    }

    bool
    Lsdb::removeCorLsa(Nlsr& pnlsr, string& key)
    {
        std::list<CorLsa >::iterator it = std::find_if( corLsdb.begin(),
                                          corLsdb.end(),
                                          bind(corLsaCompareByKey, _1, key));
        if ( it != corLsdb.end() )
        {
            if ( (*it).getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
            {
                pnlsr.getNpt().removeNpte((*it).getOrigRouter(),(*it).getOrigRouter(),pnlsr);
            }
            corLsdb.erase(it);
            return true;
        }
        return false;
    }

    bool
    Lsdb::doesCorLsaExist(string key)
    {
        std::list<CorLsa >::iterator it = std::find_if( corLsdb.begin(),
                                          corLsdb.end(),
                                          bind(corLsaCompareByKey, _1, key));
        if( it == corLsdb.end())
        {
            return false;
        }
        return true;
    }

    void
    Lsdb::printCorLsdb() //debugging
    {
        cout<<"---------------Cor LSDB-------------------"<<endl;
        for( std::list<CorLsa>::iterator it=corLsdb.begin();
                it!= corLsdb.end() ; it++)
        {
            cout<< (*it) <<endl;
        }
    }


// Adj LSA and LSDB related function starts here

    static bool
    adjLsaCompareByKey(AdjLsa& alsa, string& key)
    {
        return alsa.getAdjLsaKey()==key;
    }


    void
    Lsdb::scheduledAdjLsaBuild(Nlsr& pnlsr)
    {
        cout<<"scheduledAdjLsaBuild Called"<<endl;
        pnlsr.setIsBuildAdjLsaSheduled(0);
        if( pnlsr.getAdl().isAdjLsaBuildable(pnlsr))
        {
            int adjBuildCount=pnlsr.getAdjBuildCount();
            if(adjBuildCount>0 )
            {
                if (pnlsr.getAdl().getNumOfActiveNeighbor()>0)
                {
                    buildAndInstallOwnAdjLsa(pnlsr);
                }
                else
                {
                    string key=pnlsr.getConfParameter().getRouterPrefix()+"/2";
                    removeAdjLsa(pnlsr,key);
                    pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);
                }
                pnlsr.setAdjBuildCount(pnlsr.getAdjBuildCount()-adjBuildCount);
            }
        }
        else
        {
            pnlsr.setIsBuildAdjLsaSheduled(1);
            int schedulingTime=pnlsr.getConfParameter().getInterestRetryNumber()*
                               pnlsr.getConfParameter().getInterestResendTime();
            pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(schedulingTime),
                                               ndn::bind(&Lsdb::scheduledAdjLsaBuild, pnlsr.getLsdb(),
                                                       boost::ref(pnlsr)));
        }
    }


    bool
    Lsdb::addAdjLsa(AdjLsa &alsa)
    {
        std::list<AdjLsa >::iterator it = std::find_if( adjLsdb.begin(),
                                          adjLsdb.end(),
                                          bind(adjLsaCompareByKey, _1, alsa.getAdjLsaKey()));
        if( it == adjLsdb.end())
        {
            adjLsdb.push_back(alsa);
            return true;
        }
        return false;
    }

    std::pair<AdjLsa& , bool>
    Lsdb::getAdjLsa(string key)
    {
        std::list<AdjLsa >::iterator it = std::find_if( adjLsdb.begin(),
                                          adjLsdb.end(),
                                          bind(adjLsaCompareByKey, _1, key));
        if( it != adjLsdb.end())
        {
            return std::make_pair(boost::ref((*it)),true);
        }
        AdjLsa alsa;
        return std::make_pair(boost::ref(alsa),false);
    }



    ndn::EventId
    Lsdb::scheduleAdjLsaExpiration(Nlsr& pnlsr, string key, int seqNo, int expTime)
    {
        return pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(expTime),
                ndn::bind(&Lsdb::exprireOrRefreshAdjLsa,
                          this,boost::ref(pnlsr),key,seqNo));
    }

    bool
    Lsdb::installAdjLsa(Nlsr& pnlsr, AdjLsa &alsa)
    {
        int timeToExpire=lsaRefreshTime;
        std::pair<AdjLsa& , bool> chkAdjLsa=getAdjLsa(alsa.getAdjLsaKey());
        if ( !chkAdjLsa.second )
        {
            addAdjLsa(alsa);
            alsa.addNptEntriesForAdjLsa(pnlsr);
            pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);
            if(alsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
            {
                timeToExpire=alsa.getLifeTime();
            }
            scheduleAdjLsaExpiration(pnlsr,alsa.getAdjLsaKey(),
                                     alsa.getLsSeqNo(),timeToExpire);
        }
        else
        {
            if ( chkAdjLsa.first.getLsSeqNo() < alsa.getLsSeqNo() )
            {
                chkAdjLsa.first.setLsSeqNo(alsa.getLsSeqNo());
                chkAdjLsa.first.setLifeTime(alsa.getLifeTime());
                if ( !	chkAdjLsa.first.isLsaContentEqual(alsa))
                {
                    chkAdjLsa.first.getAdl().resetAdl();
                    chkAdjLsa.first.getAdl().addAdjacentsFromAdl(alsa.getAdl());
                    pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);
                }
                if(alsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
                {
                    timeToExpire=alsa.getLifeTime();
                }
                cancelScheduleLsaExpiringEvent(pnlsr,
                                               chkAdjLsa.first.getLsaExpiringEventId());
                chkAdjLsa.first.setLsaExpiringEventId(scheduleAdjLsaExpiration(pnlsr,
                                                      alsa.getAdjLsaKey(), alsa.getLsSeqNo(),timeToExpire));
            }
        }
        printAdjLsdb();
        return true;
    }

    bool
    Lsdb::buildAndInstallOwnAdjLsa(Nlsr& pnlsr)
    {
        AdjLsa adjLsa(pnlsr.getConfParameter().getRouterPrefix()
                      , 2
                      , pnlsr.getSm().getAdjLsaSeq()+1
                      , pnlsr.getConfParameter().getRouterDeadInterval()
                      , pnlsr.getAdl().getNumOfActiveNeighbor()
                      , pnlsr.getAdl() );
        pnlsr.getSm().setAdjLsaSeq(pnlsr.getSm().getAdjLsaSeq()+1);
        return installAdjLsa(pnlsr, adjLsa);
    }

    bool
    Lsdb::removeAdjLsa(Nlsr& pnlsr, string& key)
    {
        std::list<AdjLsa >::iterator it = std::find_if( adjLsdb.begin(),
                                          adjLsdb.end(),
                                          bind(adjLsaCompareByKey, _1, key));
        if ( it != adjLsdb.end() )
        {
            (*it).removeNptEntriesForAdjLsa(pnlsr);
            adjLsdb.erase(it);
            return true;
        }
        return false;
    }

    bool
    Lsdb::doesAdjLsaExist(string key)
    {
        std::list< AdjLsa >::iterator it = std::find_if( adjLsdb.begin(),
                                           adjLsdb.end(),
                                           bind(adjLsaCompareByKey, _1, key));
        if( it == adjLsdb.end())
        {
            return false;
        }
        return true;
    }

    std::list<AdjLsa>&
    Lsdb::getAdjLsdb()
    {
        return adjLsdb;
    }

    void
    Lsdb::setLsaRefreshTime(int lrt)
    {
        lsaRefreshTime=lrt;
    }

    void
    Lsdb::setThisRouterPrefix(string trp)
    {
        thisRouterPrefix=trp;
    }

    void
    Lsdb::exprireOrRefreshNameLsa(Nlsr& pnlsr, string lsaKey, int seqNo)
    {
        cout<<"Lsdb::exprireOrRefreshNameLsa Called "<<endl;
        cout<<"LSA Key : "<<lsaKey<<" Seq No: "<<endl;
        std::pair<NameLsa& , bool> chkNameLsa=getNameLsa(lsaKey);
        if( chkNameLsa.second )
        {
            cout<<" LSA Exists with seq no: "<<chkNameLsa.first.getLsSeqNo()<<endl;
            if ( chkNameLsa.first.getLsSeqNo() == seqNo )
            {
                if(chkNameLsa.first.getOrigRouter() == thisRouterPrefix )
                {
                    cout<<"Own Name LSA, so refreshing name LSA"<<endl;
                    chkNameLsa.first.setLsSeqNo(chkNameLsa.first.getLsSeqNo()+1);
                    pnlsr.getSm().setNameLsaSeq(chkNameLsa.first.getLsSeqNo());
                    // publish routing update
                }
                else
                {
                    cout<<"Other's Name LSA, so removing form LSDB"<<endl;
                    removeNameLsa(pnlsr, lsaKey);
                }
            }
        }
    }

    void
    Lsdb::exprireOrRefreshAdjLsa(Nlsr& pnlsr, string lsaKey, int seqNo)
    {
        cout<<"Lsdb::exprireOrRefreshAdjLsa Called "<<endl;
        cout<<"LSA Key : "<<lsaKey<<" Seq No: "<<endl;
        std::pair<AdjLsa& , bool> chkAdjLsa=getAdjLsa(lsaKey);
        if( chkAdjLsa.second )
        {
            cout<<" LSA Exists with seq no: "<<chkAdjLsa.first.getLsSeqNo()<<endl;
            if ( chkAdjLsa.first.getLsSeqNo() == seqNo )
            {
                if(chkAdjLsa.first.getOrigRouter() == thisRouterPrefix )
                {
                    cout<<"Own Adj LSA, so refreshing Adj LSA"<<endl;
                    chkAdjLsa.first.setLsSeqNo(chkAdjLsa.first.getLsSeqNo()+1);
                    pnlsr.getSm().setAdjLsaSeq(chkAdjLsa.first.getLsSeqNo());
                    // publish routing update
                }
                else
                {
                    cout<<"Other's Adj LSA, so removing form LSDB"<<endl;
                    removeAdjLsa(pnlsr, lsaKey);
                }
                // schedule Routing table calculaiton
                pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);
            }
        }
    }

    void
    Lsdb::exprireOrRefreshCorLsa(Nlsr& pnlsr, string lsaKey, int seqNo)
    {
        cout<<"Lsdb::exprireOrRefreshCorLsa Called "<<endl;
        cout<<"LSA Key : "<<lsaKey<<" Seq No: "<<endl;
        std::pair<CorLsa& , bool> chkCorLsa=getCorLsa(lsaKey);
        if( chkCorLsa.second )
        {
            cout<<" LSA Exists with seq no: "<<chkCorLsa.first.getLsSeqNo()<<endl;
            if ( chkCorLsa.first.getLsSeqNo() == seqNo )
            {
                if(chkCorLsa.first.getOrigRouter() == thisRouterPrefix )
                {
                    cout<<"Own Cor LSA, so refreshing Cor LSA"<<endl;
                    chkCorLsa.first.setLsSeqNo(chkCorLsa.first.getLsSeqNo()+1);
                    pnlsr.getSm().setCorLsaSeq(chkCorLsa.first.getLsSeqNo());
                    // publish routing update
                }
                else
                {
                    cout<<"Other's Cor LSA, so removing form LSDB"<<endl;
                    removeCorLsa(pnlsr, lsaKey);
                }
                if (pnlsr.getConfParameter().getIsHyperbolicCalc() >=1 )
                {
                    pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);
                }
            }
        }
    }


    void
    Lsdb::printAdjLsdb()
    {
        cout<<"---------------Adj LSDB-------------------"<<endl;
        for( std::list<AdjLsa>::iterator it=adjLsdb.begin();
                it!= adjLsdb.end() ; it++)
        {
            cout<< (*it) <<endl;
        }
    }

//-----utility function -----
    bool
    Lsdb::doesLsaExist(string key, int lsType)
    {
        if ( lsType == 1)
        {
            return doesNameLsaExist(key);
        }
        else if ( lsType == 2)
        {
            return doesAdjLsaExist(key);
        }
        else if ( lsType == 3)
        {
            return doesCorLsaExist(key);
        }
        return false;
    }

}//namespace nlsr

