#include "trav.h"
#include "hub/err.h"
#include <string>
using namespace hub;
//---------------------------------------------------------------------------
void TopTraverser :: operator () (void) {
    client_->haveUnit ();
    Hub :: LibIter li;
    if (theLib_ && fixedLib_) {
    	travLib (theLib_);
    } else {
	    for (li = theHub_->LibBeg(); li != theHub_->LibEnd(); li++) {
	        travLib (li->second);
        }
    }

	Hub::DesignIter di;
    if (fixedDesign_) {
        if (theDesign_) {
            client_->haveDesign (theDesign_);
            client_-> endDesign (theDesign_);
        }       // else fixed no design?  <<<<<<<<<<<<<<
    } else {
	    for (di = theHub_->DesignBeg(); di != theHub_->DesignEnd(); di++) {
	        client_->haveDesign (di->second);
	        client_-> endDesign (di->second);
        }
    }
    client_->endUnit  ();
}
//---------------------------------------------------------------------------
void  TopTraverser :: travLib (hub::Library* lib) {
    Library :: EntIter ei;

    if (fixedEntity_) {
        if (!theEntity_) theEntity_ = lib->FindEntity (items_[ent].content());
        if (theEntity_) {           // if not, we might be in the wrong library
            client_->haveLibrary (lib);
            travEnt (theEntity_);       
            client_->endLibrary (lib);
        }
    } else {
        client_->haveLibrary (lib);
	    for (ei = lib->EntBeg(); ei != lib->EntEnd(); ei++) {
	        travEnt (ei->second);
	    }
        client_->endLibrary (lib);
    }	    
}
//---------------------------------------------------------------------------
void  TopTraverser :: travEnt (hub::Entity* ent) {
    Entity :: PortProtoIter ppi;
    Entity :: ArchIter ai;
    if (fixedArch_) {
        if (!theArch_) theArch_ = ent->FindArch (items_[arch].content());
        if (theArch_) {             // good entity
            client_->haveEntity (ent);
            for (ppi = ent->PortProtoBeg(); ppi != ent->PortProtoEnd(); ppi++) {
	            client_->havePortProto (ppi->second);
            }
            client_->haveArch (theArch_);
	        client_->endArch  (theArch_);
            client_->endEntity (ent);
        }
    } else {
        client_->haveEntity (ent);
        for (ppi = ent->PortProtoBeg(); ppi != ent->PortProtoEnd(); ppi++) {
	        client_->havePortProto (ppi->second);
        }
	    for (ai = ent->ArchBeg(); ai != ent->ArchEnd(); ai++) {
	        client_->haveArch (ai->second);
	        client_->endArch (ai->second);
	    }
        client_->endEntity (ent);
    }
}
//---------------------------------------------------------------------------
void TopTraverserClient :: haveUnit (void) {}
void TopTraverserClient :: endUnit  (void) {}
void TopTraverserClient :: haveLibrary (Library*) {}
void TopTraverserClient :: endLibrary  (Library*) {}
void TopTraverserClient :: haveDesign (Design*) {}
void TopTraverserClient :: endDesign  (Design*) {}
void TopTraverserClient :: haveEntity (Entity*) {}
void TopTraverserClient :: endEntity  (Entity*) {}
void TopTraverserClient :: havePortProto (PortProto*) {}
void TopTraverserClient :: haveArch (Architecture*) {}
void TopTraverserClient :: endArch  (Architecture*) {}
//---------------------------------------------------------------------------
TopTraverserClient :: ~TopTraverserClient () { }
// ==========================================================================
void StructArchTraverser :: travNets (void) {
    StructArch :: NetIter ni;
    Net :: JoinIter ji;
    for (ni = archImpl_->NetBeg(); ni != archImpl_->NetEnd(); ni++) {
	    client_->haveNet (ni->second);
	    for (ji = ni->second->JoinBeg(); ji != ni->second->JoinEnd(); ji++) {
	        client_->haveJoined (*ji);
	    }
	    client_->endNet (ni->second);
    }
}
//---------------------------------------------------------------------------
void StructArchTraverser :: travPorts (void) {
    StructArch :: PortIter pi;
    for (pi = archImpl_->PortBeg(); pi != archImpl_->PortEnd(); pi++) {
	    client_->havePort (*pi);
    }
}
//---------------------------------------------------------------------------
void StructArchTraverser :: travPorts (const PortProto::flagsType&) {
}
//---------------------------------------------------------------------------
void StructArchTraverser :: travInsts (void) {
    StructArch :: InstIter ii;
    for (ii = archImpl_->InstBeg(); ii != archImpl_->InstEnd(); ii++) {
	    client_->haveInst (ii->second);
    }
}
//---------------------------------------------------------------------------
void StructArchTravClient :: haveNet (hub::Net*) {}
void StructArchTravClient :: endNet  (hub::Net*) {}
void StructArchTravClient :: haveJoined (hub::Joinable*) {}
void StructArchTravClient :: havePort (hub::Port <StructArch>*) {}
void StructArchTravClient :: haveInst (hub::Instance*) {}
//---------------------------------------------------------------------------
StructArchTravClient :: ~StructArchTravClient () {}
