// file: $isip/class/dstr/BiGraphVertex/BiGraphVertex.h
// version: $Id: BiGraphVertex.h 10636 2007-01-26 22:18:09Z tm334 $
//

// make sure definitions are only made once
//
#ifndef ISIP_BIGRAPH_VERTEX
#define ISIP_BIGRAPH_VERTEX

// isip include files
//
#ifndef ISIP_DOUBLE_LINKED_LIST
#include <DoubleLinkedList.h>
#endif

#ifndef ISIP_MEMORY_MANAGER
#include <MemoryManager.h>
#endif

#ifndef ISIP_STRING
#include <String.h>
#endif

// forward class definitions:
//  we must define the BiGraph class and the BiGraphArc class here first because
//  the header files might be short-circuited by the ifndef.
//
template<class TObject> class BiGraph;
template<class TObject> class BiGraphArc;

// BiGraphVertex: a generic BiGraphVertex. the main purpose of a vertex is
// to hold a list of arcs originating from the given vertex.
//
template<class TObject>
class BiGraphVertex : public Node<TObject> {

  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:
  
  // define the class name
  //
  static const String CLASS_NAME;

  //----------------------------------------
  //
  // i/o related constants
  //
  //----------------------------------------  
  
  static const String DEF_PARAM;
  
  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------

  // default values
  //
  
  // default arguments to methods
  //
  
  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  
  
  static const long ERR = 41100;
  static const long ERR_NULLD = 41101;
  static const long ERR_NOPAR = 41102;
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // adjacency list manipulation methods
  //
  DoubleLinkedList< BiGraphArc<TObject> > parents_d;    
  DoubleLinkedList< BiGraphArc<TObject> > children_d;
  
  // what BiGraph does this vertex belong to
  //
  BiGraph<TObject>* parent_graph_d;

  // define the memory manager
  //
  static MemoryManager mgr_d;
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:

  // static methods
  //
  static const String& name();

  // this class doesn't have a diagnose method, its functionality is
  // tested in BiGraph::diagnose
  //
  
  // debug methods:
  //  setDebug is inherited from the DoubleLinkedList template class
  //
  boolean debug(const unichar* message) const;
  
  // method: destructor
  //
  ~BiGraphVertex() {
    removeAllArcsChild();
    removeAllArcsParent();    
  }

  // method: default constructor
  //  
  BiGraphVertex() {
    parent_graph_d = (BiGraph<TObject>*)NULL;
    setAllocationModeChild(DstrBase::USER);
    setAllocationModeParent(DstrBase::USER);
  }

  // method: copy constructor
  //  
  BiGraphVertex(const BiGraphVertex<TObject>& arg) {
    parent_graph_d = (BiGraph<TObject>*)NULL;
    setAllocationModeChild(DstrBase::USER);
    setAllocationModeParent(DstrBase::USER);    
    assign(arg);
  }

  // assign methods
  //
  boolean assign(const BiGraphVertex<TObject>& copy_vertex);

  // method: operator=
  //
  BiGraphVertex<TObject>& operator=(const BiGraphVertex<TObject>& arg) {
    assign(arg);
    return *this;
  }

  // i/o methods:
  //  these methods are not needed since BiGraph takes care of it's own I/O.
  //
  
  // method: eq
  //  determines if the contents of the vertex are equivalent.
  //  adjacency lists & weights are ignored.
  //
  boolean eq(const BiGraphVertex<TObject>& arg) const {
    return Node<TObject>::eq(arg);
  }
  
  // method: new
  //
  void* operator new(size_t size) {
    return mgr_d.get();
  }

  // method: new[]
  //
  void* operator new[](size_t size) {
    return mgr_d.getBlock(size);
  }

  // method: delete
  //
  void operator delete(void* ptr) {
    mgr_d.release(ptr);
  }

  // method: delete[]
  //
  void operator delete[](void* ptr) {
    mgr_d.releaseBlock(ptr);
  }

  // method: setGrowSize
  //
  static boolean setGrowSize(long grow_size) {
    return (mgr_d.setGrow(grow_size));
  }

  // other memory management methods:
  //
  boolean clear(Integral::CMODE cmode = Integral::DEF_CMODE);

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  parent bigraph manipulation methods
  //
  //---------------------------------------------------------------------------

  // method: setParentGraph
  //
  boolean setParentGraph(BiGraph<TObject>* parent) {
    parent_graph_d = parent;
    return true;
  }

  // method: getParentGraph
  //
  BiGraph<TObject>* getParentGraph() const {
    return parent_graph_d;
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  vertex manipulation methods
  //
  //---------------------------------------------------------------------------
  
  // insert/remove a vertex to/from the adjacency list:
  //  these methods assume that the user is taking care of updating the
  //  parent BiGraphs, end vertices, etc.
  //
  boolean insertArcChild(BiGraphVertex<TObject>* vertex,
		 double weight = BiGraphArc<TObject>::DEF_WEIGHT,
		 boolean is_epsilon = BiGraphArc<TObject>::DEF_EPSILON);
  boolean insertArcParent(BiGraphVertex<TObject>* vertex,
		 double weight = BiGraphArc<TObject>::DEF_WEIGHT,
		 boolean is_epsilon = BiGraphArc<TObject>::DEF_EPSILON);  
  boolean insertArcChild(BiGraphVertex<TObject>* vertex,
		 boolean is_epsilon = BiGraphArc<TObject>::DEF_EPSILON);
  boolean insertArcParent(BiGraphVertex<TObject>* vertex,
		 boolean is_epsilon = BiGraphArc<TObject>::DEF_EPSILON);

  boolean removeArcChild(BiGraphVertex<TObject>* vertex);
  boolean removeArcParent(BiGraphVertex<TObject>* vertex);  
  boolean removeArcChild();
  boolean removeArcParent();  
  boolean removeAllArcsChild();
  boolean removeAllArcsParent();  
  
  // is this vertex adjacent?
  //
  boolean isAdjacentChild(BiGraphVertex<TObject>* vertex) const;
  boolean isAdjacentParent(BiGraphVertex<TObject>* vertex) const;  

  // method: isStart
  //
  boolean isStart() const {
    if (parent_graph_d == (BiGraph<TObject>*)NULL) {
      return Error::handle(name(), L"isStart - undefined parent", Error::ARG, __FILE__, __LINE__);
    }
    return (this == parent_graph_d->getStart());
  }

  // method: isTerm
  //
  boolean isTerm() const {
    if (parent_graph_d == (BiGraph<TObject>*)NULL) {
      return Error::handle(name(), L"isTerm - undefined parent", Error::ARG, __FILE__, __LINE__);
    }
    return (this == parent_graph_d->getTerm());
  }
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  vertex comparison methods
  //
  //---------------------------------------------------------------------------

  // compares the siblings of the two vertices and arc weights to see if
  // the two vertices has a similar structure
  //
  boolean compareVertices(const BiGraphVertex<TObject>& compare_vertex_a) const;

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  adjacency list retrieval methods
  //
  //---------------------------------------------------------------------------

  // method: getParents
  //
  DoubleLinkedList< BiGraphArc<TObject> >* getParents() {
    return &parents_d;
  }
  
  // method: getChildren
  //  
  DoubleLinkedList< BiGraphArc<TObject> >* getChildren() {
    return &children_d;
  }  

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  adjacency list positioning methods
  //
  //--------------------------------------------------------------------------

  // method: gotoFirstChild
  //
  boolean gotoFirstChild() {
    return children_d.gotoFirst();
  }

  // method: gotoLastChild
  //
  boolean gotoLastChild() {
    return children_d.gotoLast();
  }

  // method: gotoNextChild
  //
  boolean gotoNextChild() {
    return children_d.gotoNext();
  }

  // method: gotoPrevChild
  //
  boolean gotoPrevChild() {
    return children_d.gotoPrev();
  }

  // method: gotoMarkChild
  //
  boolean gotoMarkChild() {
    return children_d.gotoMark();
  }

  // method: gotoPositionChild
  //
  boolean gotoPositionChild(long arg) {
    return children_d.gotoPosition(arg);
  }

  // method: getPositionChild
  //
  long getPositionChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> > & >
      (children_d).getPosition();
  }

  // method: gotoFirstParent
  //
  boolean gotoFirstParent() {
    return parents_d.gotoFirst();
  }

  // method: gotoLastParent
  //
  boolean gotoLastParent() {
    return parents_d.gotoLast();
  }  

  // method: gotoNextParent
  //
  boolean gotoNextParent() {
    return parents_d.gotoNext();
  }

  // method: gotoPrevParent
  //
  boolean gotoPrevParent() {
    return parents_d.gotoPrev();
  }

  // method: gotoMarkParent
  //
  boolean gotoMarkParent() {
    return parents_d.gotoMark();
  }

  // method: gotoPositionParent
  //
  boolean gotoPositionParent(long arg) {
    return parents_d.gotoPosition(arg);
  }

  // method: getPositionParent
  //
  long getPositionParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).getPosition();
  }  

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  adjacency list marking methods
  //
  //--------------------------------------------------------------------------

  // method: markIsSetChild
  //
  boolean markIsSetChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).markIsSet();
  }

  // method: isMarkedElementChild
  //
  boolean isMarkedElementChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).isMarkedElement();
  }

  // method: clearMarkChild
  //
  boolean clearMarkChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).clearMark();
  }

  // method: setMarkChild
  //
  boolean setMarkChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).setMark();
  }

  // method: markIsSetParent
  //
  boolean markIsSetParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).markIsSet();
  }

  // method: isMarkedElementParent
  //
  boolean isMarkedElementParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).isMarkedElement();
  }

  // method: clearMarkParent
  //
  boolean clearMarkParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).clearMark();
  }

  // method: setMarkParent
  //
  boolean setMarkParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).setMark();
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  adjacency list access methods
  //
  //--------------------------------------------------------------------------

  // method: getFirstChild
  //
  BiGraphArc<TObject>* getFirstChild() {
    return children_d.getFirst();    
  }

  // method: getLastChild
  //
  BiGraphArc<TObject>* getLastChild() {
    return children_d.getLast();    
  }

  // method: getNextChild
  //
  BiGraphArc<TObject>* getNextChild() {
    return children_d.getNext();    
  }  

  // method: getPrevChild
  //
  BiGraphArc<TObject>* getPrevChild() {
    return children_d.getPrev();    
  }

  // method: getMarkChild
  //
  BiGraphArc<TObject>* getMarkChild() {
    return children_d.getMark();    
  }

  // method: getCurrChild
  //
  BiGraphArc<TObject>* getCurrChild() {
    return children_d.getCurr();    
  }

  // method: getFirstChild
  //
  BiGraphArc<TObject>* getFirstChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).getFirst();    
  }

  // method: getLastChild
  //
  BiGraphArc<TObject>* getLastChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).getLast();    
  }

  // method: getNextChild
  //
  BiGraphArc<TObject>* getNextChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).getNext();    
  }  

  // method: getPrevChild
  //
  BiGraphArc<TObject>* getPrevChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).getPrev();    
  }

  // method: getMarkChild
  //
  BiGraphArc<TObject>* getMarkChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).getMark();    
  }

  // method: getCurrChild
  //
  BiGraphArc<TObject>* getCurrChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).getCurr();    
  }  

  // method: getFirstParent
  //
  BiGraphArc<TObject>* getFirstParent() {
    return parents_d.getFirst();    
  }

  // method: getLastParent
  //
  BiGraphArc<TObject>* getLastParent() {
    return parents_d.getLast();    
  }

  // method: getNextParent
  //
  BiGraphArc<TObject>* getNextParent() {
    return parents_d.getNext();    
  }  

  // method: getPrevParent
  //
  BiGraphArc<TObject>* getPrevParent() {
    return parents_d.getPrev();    
  }

  // method: getMarkParent
  //
  BiGraphArc<TObject>* getMarkParent() {
    return parents_d.getMark();    
  }

  // method: getCurrParent
  //
  BiGraphArc<TObject>* getCurrParent() {
    return parents_d.getCurr();    
  }

  // method: getFirstParent
  //
  BiGraphArc<TObject>* getFirstParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).getFirst();    
  }

  // method: getLastParent
  //
  BiGraphArc<TObject>* getLastParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).getLast();    
  }

  // method: getNextParent
  //
  BiGraphArc<TObject>* getNextParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).getNext();    
  }  

  // method: getPrevParent
  //
  BiGraphArc<TObject>* getPrevParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).getPrev();    
  }

  // method: getMarkParent
  //
  BiGraphArc<TObject>* getMarkParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).getMark();    
  }

  // method: getCurrParent
  //
  BiGraphArc<TObject>* getCurrParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).getCurr();    
  }  

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  adjacency list insert-remove methods
  //
  //--------------------------------------------------------------------------

  // method: insertChild
  //
  boolean insertChild(BiGraphArc<TObject>* arg) {
    return children_d.insert(arg);
  }

  // method: insertChild
  //
  boolean insertChild(DoubleLinkedList<BiGraphArc<TObject> >& arg) {
    return children_d.insert(arg);
  }

  // method: removeChild
  //
  boolean removeChild(BiGraphArc<TObject>*& arg) {
    return children_d.remove(arg);
  }  

  // method: removeChild
  //
  boolean removeChild() {
    return children_d.remove();
  }      

  // method: insertFirstChild
  //
  boolean insertFirstChild(BiGraphArc<TObject>* arg) {
    return children_d.insertFirst(arg);
  }

  // method: insertFirstChild
  //
  boolean insertFirstChild(DoubleLinkedList<BiGraphArc<TObject> >& arg) {
    return children_d.insertFirst(arg);    
  }

  // method: removeFirstChild
  //
  boolean removeFirstChild(BiGraphArc<TObject>*& arg) {
    return children_d.removeFirst(arg);    
  }

  // method: removeFirstChild
  //
  boolean removeFirstChild() {
    return children_d.removeFirst();    
  }

  // method: insertLastChild
  //
  boolean insertLastChild(BiGraphArc<TObject>* arg) {
    return children_d.insertLast(arg);
  }
  
  // method: insertLastChild
  //
  boolean insertLastChild(DoubleLinkedList<BiGraphArc<TObject> >& arg) {
    return children_d.insertLast(arg);    
  }

  // method: removeLastChild
  //
  boolean removeLastChild(BiGraphArc<TObject>*& arg) {
    return children_d.removeLast(arg);    
  }

  // method: removeLastChild
  //
  boolean removeLastChild() {
    return children_d.removeLast();    
  }

  // method: insertParent
  //
  boolean insertParent(BiGraphArc<TObject>* arg) {
    return parents_d.insert(arg);
  }

  // method: insertParent
  //
  boolean insertParent(DoubleLinkedList<BiGraphArc<TObject> >& arg) {
    return parents_d.insert(arg);
  }  

  // method: removeParent
  //
  boolean removeParent(BiGraphArc<TObject>*& arg) {
    return parents_d.remove(arg);
  }  

  // method: removeParent
  //
  boolean removeParent() {
    return parents_d.remove();
  }      

  // method: insertFirstParent
  //
  boolean insertFirstParent(BiGraphArc<TObject>* arg) {
    return parents_d.insertFirst(arg);
  }

  // method: insertFirstParent
  //
  boolean insertFirstParent(DoubleLinkedList<BiGraphArc<TObject> >& arg) {
    return parents_d.insertFirst(arg);    
  }

  // method: removeFirstParent
  //
  boolean removeFirstParent(BiGraphArc<TObject>*& arg) {
    return parents_d.removeFirst(arg);    
  }

  // method: removeFirstParent
  //
  boolean removeFirstParent() {
    return parents_d.removeFirst();    
  }

  // method: insertLastParent
  //
  boolean insertLastParent(BiGraphArc<TObject>* arg) {
    return parents_d.insertLast(arg);
  }
  
  // method: insertLastParent
  //
  boolean insertLastParent(DoubleLinkedList<BiGraphArc<TObject> >& arg) {
    return parents_d.insertLast(arg);    
  }

  // method: removeLastParent
  //
  boolean removeLastParent(BiGraphArc<TObject>*& arg) {
    return parents_d.removeLast(arg);    
  }

  // method: removeLastParent
  //
  boolean removeLastParent() {
    return parents_d.removeLast();    
  }  

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  adjacency list property methods
  //
  //--------------------------------------------------------------------------

  // method: isEmptyChild
  //
  boolean isEmptyChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).isEmpty();
  }

  // method: isFirstChild
  //
  boolean isFirstChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).isFirst();
  }

  // method: isLastChild
  //
  boolean isLastChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).isLast();
  }

  // method: lengthChild
  //
  long lengthChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).length();
  }

  // method: findChild
  //
  boolean findChild(const BiGraphArc<TObject>* arg) {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).find(arg);
  }

  // method: containsChild
  //
  boolean containsChild(const BiGraphArc<TObject>* arg) const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).contains(arg);
  }

  // method: isEmptyParent
  //
  boolean isEmptyParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).isEmpty();
  }

  // method: isFirstParent
  //
  boolean isFirstParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).isFirst();
  }

  // method: isLastParent
  //
  boolean isLastParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).isLast();
  }

  // method: lengthParent
  //
  long lengthParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).length();
  }

  // method: findParent
  //
  boolean findParent(const BiGraphArc<TObject>* arg) {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).find(arg);
  }

  // method: containsParent
  //
  boolean containsParent(const BiGraphArc<TObject>* arg) const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).contains(arg);
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  adjacency list ordering methods  
  //
  //-------------------------------------------------------------------------- 

  // method: sortChild
  //
  boolean sortChild(Integral::ORDER sort_order = Integral::ASCENDING,
	       DstrBase::SORT_ALGO = DstrBase::DEF_SORT_ALGO) {
    return children_d.sort(sort_order);
  }

  // method: reverseChild
  //
  boolean reverseChild() {
    return children_d.reverse();
  }

  // method: swapChild
  //
  boolean swapChild(long i, long j) {
    return children_d.swap(i, j);
  }

  // method: sortParent
  //
  boolean sortParent(Integral::ORDER sort_order = Integral::ASCENDING,
	       DstrBase::SORT_ALGO = DstrBase::DEF_SORT_ALGO) {
    return parents_d.sort(sort_order);
  }

  // method: reverseParent
  //
  boolean reverseParent() {
    return parents_d.reverse();
  }

  // method: swapParent
  //
  boolean swapParent(long i, long j) {
    return parents_d.swap(i, j);
  }  

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  adjacency list allocation methods
  //
  //--------------------------------------------------------------------------

  // method: getAllocationModeChild
  //
  DstrBase::ALLOCATION getAllocationModeChild() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (children_d).getAllocationMode();
  }

  // method: setAllocationModeChild
  //
  boolean setAllocationModeChild(DstrBase::ALLOCATION arg) {
    return children_d.setAllocationMode(arg);
  }


  // method: getAllocationModeParent
  //
  DstrBase::ALLOCATION getAllocationModeParent() const {
    return const_cast<DoubleLinkedList<BiGraphArc<TObject> >& >
      (parents_d).getAllocationMode();
  }

  // method: setAllocationModeParent
  //
  boolean setAllocationModeParent(DstrBase::ALLOCATION arg) {
    return parents_d.setAllocationMode(arg);
  }  
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

  // friend class
  //
  template <class TObject_diagnose> 
  friend class BiGraphVertexDiagnose;
};

// in order to allow BiGraph to reference BiGraphVertex's constants, it
// must be included after the class definition.
//
#ifndef ISIP_BI_GRAPH
#include <BiGraph.h>
#endif

#ifndef ISIP_BIGRAPH_ARC
#include <BiGraphArc.h>
#endif

//-----------------------------------------------------------------------------
//
// we define non-integral constants at the end of class definition for
// templates (for non-templates these are defined in the default constructor)
//      
//-----------------------------------------------------------------------------

// constants: required constants such as the class name
//
template <class TObject>
const String BiGraphVertex<TObject>::CLASS_NAME(L"BiGraphVertex");

template <class TObject>
const String BiGraphVertex<TObject>::DEF_PARAM(L"vertex");

// static instantiations: the memory manager
//
template <class TObject>
MemoryManager BiGraphVertex<TObject>::mgr_d(sizeof(BiGraphVertex<TObject>),
					  CLASS_NAME);

// below are all the methods for the BiGraphVertex template class
//      

// ---------------------------------------------------------------------
//
// required static methods
//
//----------------------------------------------------------------------

// method: name
//
// arguments: none
//
// return: a static String& containing the class name
//
// this method returns the class name
//
template<class TObject>
const String& BiGraphVertex<TObject>::name() {

  // create the static name string for this class and return it
  //
  static String cname(CLASS_NAME);
  cname.clear();
  cname.concat(CLASS_NAME);
  cname.concat(L"<");
  cname.concat(TObject::name());
  cname.concat(L">");

  // return the name
  //
  return cname;
}

// ---------------------------------------------------------------------
//
// required debug methods
//
//----------------------------------------------------------------------

// method: debug
//
// arguments:
//  const unichar* message: (input) information message
//
// return: a boolean value indicating status
//
// this method dumps the contents of an object to the console
// 
template<class TObject>
boolean BiGraphVertex<TObject>::debug(const unichar* message_a) const {

  // build a debug string
  //
  String output;
  String value;
  output.debugStr(name(), message_a, L"");
  Console::put(output);
  
  Console::increaseIndention();

  // dump a pointer to the current vertex
  //
  value.assign(this);
  output.debugStr(name(), message_a, L"this", value);
  Console::put(output);
  
  // dump a pointer to the parent BiGraph
  //
  value.assign(parent_graph_d);
  output.debugStr(name(), message_a, L"parent_graph_d", value);
  Console::put(output);

  // dump the internal item if it exists
  //
  Node<TObject>::debug(L"item");

  // call the parent debug method to debug the list itself
  //
  parents_d.debug(L"parents arcs");
  
  // call the parent debug method to debug the list itself
  //
  children_d.debug(L"children arcs");

  // that's it for sub-items, decrease indentation
  //
  Console::decreaseIndention();

  // exit gracefully
  // 
  return true;
}

//------------------------------------------------------------------------
//
//  required assign methods
//
//-------------------------------------------------------------------------

// method: assign
//
// arguments:
//  const BiGraphVertex<TObject>& arg: (input) the vertex to copy
//
// return: a boolean value indicating status
//
// this method copies the contents of the input to this list
//
template<class TObject>
boolean BiGraphVertex<TObject>::assign(const BiGraphVertex<TObject>& arg_a) {

  // it may be necessary to clear this vertex
  //
  clear();
  
  // call the parent assign method which handles the arc list elements
  //
  children_d.assign(*(const_cast<BiGraphVertex<TObject>& >
		      (arg_a).getChildren()));

  // call the parent assign method which handles the arc list elements
  //
  parents_d.assign(*(const_cast<BiGraphVertex<TObject>& >
		     (arg_a).getParents()));
  
  // call the Node assign method to assign the object
  //
  Node<TObject>::assign(arg_a);

  // set the parent BiGraph
  //
  setParentGraph(arg_a.parent_graph_d);

  // exit gracefully
  //
  return true;
}

//-------------------------------------------------------------------------
//
//  required clear method
//
//-------------------------------------------------------------------------

// method: clear
//
// arguments:
//  Integral::CMODE cmode_a: (input) clear mode
//
// return: a boolean value indicating status
//
// this method clears the reference to the internal data.
// 
template<class TObject>
boolean BiGraphVertex<TObject>::clear(Integral::CMODE cmode_a) {

  // switch on cmode
  //
  if (cmode_a == Integral::RETAIN) {

    if (this->item_d != (TObject*)NULL) {
      this->item_d->clear(cmode_a);
    }
  }

  else if ((cmode_a == Integral::RESET) || (cmode_a == Integral::RELEASE)) {
          
    // clear the references to the data
    //
    this->item_d = (TObject*)NULL;

    // clear the reference to the parent BiGraph
    //
    parent_graph_d = (BiGraph<TObject>*)NULL;    
  }
  
  else {
    
    // deallocate the allocated memory if necessary
    //
    if (this->item_d != (TObject*)NULL) {
      this->item_d->clear(Integral::FREE);
      delete this->item_d;
      this->item_d = (TObject*)NULL;
    }

    // clear the reference to the parent BiGraph
    //
    parent_graph_d = (BiGraph<TObject>*)NULL;
  }

  // clear the arc list
  //
  boolean return_val =  removeAllArcsChild();
  return_val &= removeAllArcsParent();

  // exit gracefully
  //
  return return_val;
}

//---------------------------------------------------------------------------
//
// class-specific public methods:
//  vertex manipulation methods
//
//---------------------------------------------------------------------------
  
// method: insertArcChild
//
// arguments:
//  BiGraphVertex<TObject>* vertex: (input) the vertex to connect to
//  double weight: (input) the weight on the generated arc
//  boolean is_epsilon: (input) is this an epsilon transition?
//
// return: a boolean value indicating status
//
// this method inserts a weighted arc connecting this vertex to the input
// vertex.
//
template<class TObject>
boolean BiGraphVertex<TObject>::insertArcChild(BiGraphVertex<TObject>* vertex_a, double weight_a, boolean is_epsilon_a) {

  // check that the input vertex is not null
  //
  if (vertex_a == (BiGraphVertex<TObject>*)NULL) {
    return Error::handle(name(), L"insertArcChild", Error::ARG,
			 __FILE__, __LINE__);
  }

  // create a new Arc
  //
  BiGraphArc<TObject>* new_arc = new BiGraphArc<TObject>(vertex_a, weight_a);
  new_arc->setEpsilon(is_epsilon_a);

  // insert the arc to the list
  //
  insertChild(new_arc);
  
  // exit gracefully
  //
  return true;
}

// method: insertArcParent
//
// arguments:
//  BiGraphVertex<TObject>* vertex: (input) the vertex to connect to
//  double weight: (input) the weight on the generated arc
//  boolean is_epsilon: (input) is this an epsilon transition?
//
// return: a boolean value indicating status
//
// this method inserts a weighted arc connecting this vertex to the input
// vertex.
//
template<class TObject>
boolean BiGraphVertex<TObject>::insertArcParent(BiGraphVertex<TObject>* vertex_a, double weight_a, boolean is_epsilon_a) {

  // check that the input vertex is not null
  //
  if (vertex_a == (BiGraphVertex<TObject>*)NULL) {
    return Error::handle(name(), L"insertArcParent", Error::ARG,
			 __FILE__, __LINE__);
  }

  // create a new Arc
  //
  BiGraphArc<TObject>* new_arc = new BiGraphArc<TObject>(vertex_a, weight_a);
  new_arc->setEpsilon(is_epsilon_a);

  // insert the arc to the list
  //
  insertParent(new_arc);

  // exit gracefully
  //
  return true;
}

// method: insertArcChild
//
// arguments:
//  BiGraphVertex<TObject>* vertex: (input) the vertex to connect to
//  boolean is_epsilon: (input) is this an epsilon transition?
//
// return: a boolean value indicating status
//
// this method inserts an arc connecting this vertex to the input
// vertex.
//
template<class TObject>
boolean BiGraphVertex<TObject>::insertArcChild(BiGraphVertex<TObject>* vertex_a, boolean is_epsilon_a) {

  // check that the input vertex is not null
  //
  if (vertex_a == (BiGraphVertex<TObject>*)NULL) {
    return Error::handle(name(), L"insertArcChild", Error::ARG, __FILE__,
                         __LINE__);
  }

  // create a new Arc
  //
  BiGraphArc<TObject>* new_arc = new BiGraphArc<TObject>(vertex_a);
  new_arc->setEpsilon(is_epsilon_a);

  // insert the arc to the list
  //
  insertChild(new_arc);

  // exit gracefully
  //
  return true;
}

// method: insertArcParent
//
// arguments:
//  BiGraphVertex<TObject>* vertex: (input) the vertex to connect to
//  boolean is_epsilon: (input) is this an epsilon transition?
//
// return: a boolean value indicating status
//
// this method inserts an arc connecting this vertex to the input
// vertex.
//
template<class TObject>
boolean BiGraphVertex<TObject>::insertArcParent(BiGraphVertex<TObject>* vertex_a, boolean is_epsilon_a) {

  // check that the input vertex is not null
  //
  if (vertex_a == (BiGraphVertex<TObject>*)NULL) {
    return Error::handle(name(), L"insertArcParent", Error::ARG, __FILE__,
                         __LINE__);
  }

  // create a new Arc
  //
  BiGraphArc<TObject>* new_arc = new BiGraphArc<TObject>(vertex_a);
  new_arc->setEpsilon(is_epsilon_a);

  // insert the arc to the list
  //
  insertParent(new_arc);

  // exit gracefully
  //
  return true;
}

// method: removeArcChild
//
// arguments:
//  BiGraphVertex<TObject>* vertex: (input) the vertex to unlink from
//
// return: a boolean value indicating status
//
// this method unlinks this vertex from the input vertex. if the BiGraph is
// not directed, then an arc from the input vertex is removed as well
//
template<class TObject>
boolean BiGraphVertex<TObject>::removeArcChild(BiGraphVertex<TObject>* vertex_a) {

  // make sure the list is not empty
  //
  if (this->isEmptyChild()) {
    return false;
  }

  // save the current state
  //
  this->setMarkChild();
  
  // find the input vertex in the adjacency list by looping over all arcs
  //
  BiGraphArc<TObject>* tmp_item = (BiGraphArc<TObject>*)NULL;  
  if (this->gotoFirstChild()) {
    tmp_item = this->getCurrChild();
  }

  // declare temporary objects
  //
  BiGraphVertex<TObject>* tmp_vert = (BiGraphVertex<TObject>*) NULL;

  // loop over each element and look for the input vertex
  //
  boolean vertex_found = false;
  while ((tmp_item != (BiGraphArc<TObject>*)NULL) &&
	 !vertex_found) {

    // get the vertex out of the arc
    //
    tmp_vert = tmp_item->getVertex();

    // check to see if the found vertex is the one we are looking for
    //
    if (tmp_vert == vertex_a) {
      vertex_found = true;
    }
    else {
      if (this->gotoNextChild()) {
	tmp_item = this->getCurrChild();
      }
      else {
	tmp_item = (BiGraphArc<TObject>*)NULL;
      }
    }
  }

  // if we found the vertex then break the arcs, else return an error.
  //
  if (vertex_found) {

    // if the found vertex was at the current node position then remove the
    // node
    //
    if (this->getMarkChild() == tmp_item) {

      // remove the arc from the graph
      //
      boolean status = false;
      BiGraphArc<TObject>* graph_arc;
      status = removeChild(graph_arc);
      delete graph_arc;

      if (!status) {
	return false;
      }
    }
    else {

      // remove the node
      //
      boolean status = false;
      BiGraphArc<TObject>* graph_arc;
      status = removeChild(graph_arc);
      delete graph_arc;
      
      if (!status) {
	return false;
      }
    }
  }
  else {
    return false;
  }

  // restore the saved state
  //
  this->gotoMarkChild();
  
  // exit gracefully
  //
  return true;
}

// method: removeArcParent
//
// arguments:
//  BiGraphVertex<TObject>* vertex: (input) the vertex to unlink from
//
// return: a boolean value indicating status
//
// this method unlinks this vertex from the input vertex. if the BiGraph is
// not directed, then an arc from the input vertex is removed as well
//
template<class TObject>
boolean BiGraphVertex<TObject>::removeArcParent(BiGraphVertex<TObject>* vertex_a) {

  // make sure the list is not empty
  //
  if (this->isEmptyParent()) {
    return false;
  }

  // save the current state
  //
  this->setMarkParent();
  
  // find the input vertex in the adjacency list by looping over all arcs
  //
  BiGraphArc<TObject>* tmp_item = (BiGraphArc<TObject>*)NULL;  
  if (this->gotoFirstParent()) {
    tmp_item = this->getCurrParent();
  }

  // declare temporary objects
  //
  BiGraphVertex<TObject>* tmp_vert = (BiGraphVertex<TObject>*) NULL;

  // loop over each element and look for the input vertex
  //
  boolean vertex_found = false;
  while ((tmp_item != (BiGraphArc<TObject>*)NULL) &&
	 !vertex_found) {

    // get the vertex out of the arc
    //
    tmp_vert = tmp_item->getVertex();

    // check to see if the found vertex is the one we are looking for
    //
    if (tmp_vert == vertex_a) {
      vertex_found = true;
    }
    else {
      if (this->gotoNextParent()) {
	tmp_item = this->getCurrParent();
      }
      else {
	tmp_item = (BiGraphArc<TObject>*)NULL;
      }
    }
  }

  // if we found the vertex then break the arcs, else return an error.
  //
  if (vertex_found) {

    // if the found vertex was at the current node position then remove the
    // node
    //
    if (this->getMarkParent() == tmp_item) {

      // remove the arc from the graph
      //
      boolean status = false;
      BiGraphArc<TObject>* graph_arc;
      status = removeParent(graph_arc);
      delete graph_arc;

      if (!status) {
	return false;
      }
    }
    else {

      // remove the node
      //
      boolean status = false;
      BiGraphArc<TObject>* graph_arc;
      status = removeParent(graph_arc);
      delete graph_arc;
      
      if (!status) {
	return false;
      }
    }
  }
  else {
    return false;
  }

  // restore the saved state
  //
  this->gotoMarkParent();
  
  // exit gracefully
  //
  return true;
}

// method: removeArcChild
//
// arguments: none
//
// return: a boolean value indicating status
//
// this method unlinks this vertex from the vertex linked by the current arc
// in the list. if the BiGraph is not directed, then an arc from the found
// vertex is removed as well
//
template<class TObject>
boolean BiGraphVertex<TObject>::removeArcChild() {

  // if the adjacency list is empty then return false
  //
  if (isEmptyChild()) {
    return false;
  }

  // remove this arc
  //
  boolean status = false;
  BiGraphArc<TObject>* bigraph_arc;  
  status = removeChild(bigraph_arc);
  delete bigraph_arc;
  
  // exit gracefully
  //
  return status;
}

// method: removeArcParent
//
// arguments: none
//
// return: a boolean value indicating status
//
// this method unlinks this vertex from the vertex linked by the current arc
// in the list. if the BiGraph is not directed, then an arc from the found
// vertex is removed as well
//
template<class TObject>
boolean BiGraphVertex<TObject>::removeArcParent() {

  // if the adjacency list is empty then return false
  //
  if (isEmptyParent()) {
    return false;
  }

  // remove this arc
  //
  boolean status = false;
  BiGraphArc<TObject>* bigraph_arc;  
  status = removeParent(bigraph_arc);
  delete bigraph_arc;
  
  // exit gracefully
  //
  return status;
}

// method: removeAllArcsChild
//
// arguments: none
//
// return: a boolean value indicating status
//
// this method removes all arcs extending from this vertex
//
template<class TObject>
boolean BiGraphVertex<TObject>::removeAllArcsChild() {

  // declare a return value
  //
  boolean return_val = true;

  // loop until no arcs remain
  //
  while (!isEmptyChild()) {
    
    // remove the forward link
    //
    boolean status = false;
    BiGraphArc<TObject>* bigraph_arc;
    status = removeChild(bigraph_arc);
    delete bigraph_arc;
    
    // exit gracefully
    //
    return_val &= status;    
  }

  // exit gracefully
  //
  return return_val;
}

// method: removeAllArcsParent
//
// arguments: none
//
// return: a boolean value indicating status
//
// this method removes all arcs extending from this vertex
//
template<class TObject>
boolean BiGraphVertex<TObject>::removeAllArcsParent() {

  // declare a return value
  //
  boolean return_val = true;

  // loop until no arcs remain
  //
  while (!isEmptyParent()) {
    
    // remove the forward link
    //
    boolean status = false;
    BiGraphArc<TObject>* bigraph_arc;
    status = removeParent(bigraph_arc);
    delete bigraph_arc;
    
    // exit gracefully
    //
    return_val &= status;    
  }  

  // exit gracefully
  //
  return return_val;
}

// method: isAdjacentChild
//
// arguments:
//  BiGraphVertex<TObject>* vertex: (input) the vertex to find
//
// return: boolean flag indicating whether or not the vertex was found
//
// this method finds the input vertex in the adjacency list for this
// vertex
//
template<class TObject>
boolean BiGraphVertex<TObject>::isAdjacentChild(BiGraphVertex<TObject>*
						vertex_a) const {

  // make sure the list is not empty
  //
  if (isEmptyChild()) {
    return false;
  }

  // save the current state
  //
  this->setMarkChild();
  
  // find the input vertex in the adjacency list by looping over all arcs
  //
  BiGraphArc<TObject>* tmp_item = (BiGraphArc<TObject> *)NULL;
  if (const_cast<BiGraphVertex<TObject>* >(this)->gotoFirstChild()) {
    tmp_item = this->getCurrChild();
  }

  // declare temporary objects
  //
  BiGraphVertex<TObject>* tmp_vert = (BiGraphVertex<TObject>*) NULL;

  // loop over each element and look for the input vertex
  //
  boolean vertex_found = false;
  while ((tmp_item != (BiGraphArc<TObject> *)NULL) &&
	 !vertex_found) {

    // get the vertex out of the node
    //
    tmp_vert = tmp_item->getVertex();

    // check to see if the found vertex is the one we are looking for
    //
    if (tmp_vert == vertex_a) {
      vertex_found = true;
    }
    else {
      if (const_cast<BiGraphVertex<TObject>* >(this)->gotoNextChild()) {
	tmp_item = this->getCurrChild();
      }
      else {
	tmp_item = (BiGraphArc<TObject> *)NULL;
      }
    }
  }

  // restore the saved state
  //
  const_cast<BiGraphVertex<TObject>* >(this)->gotoMarkChild();
  
  // exit gracefully
  //
  return vertex_found;
}

// method: isAdjacentParent
//
// arguments:
//  BiGraphVertex<TObject>* vertex: (input) the vertex to find
//
// return: boolean flag indicating whether or not the vertex was found
//
// this method finds the input vertex in the adjacency list for this
// vertex
//
template<class TObject>
boolean BiGraphVertex<TObject>::isAdjacentParent(BiGraphVertex<TObject>*
						vertex_a) const {

  // make sure the list is not empty
  //
  if (isEmptyParent()) {
    return false;
  }

  // save the current state
  //
  this->setMarkParent();
  
  // find the input vertex in the adjacency list by looping over all arcs
  //
  BiGraphArc<TObject>* tmp_item = (BiGraphArc<TObject> *)NULL;
  if (const_cast<BiGraphVertex<TObject>* >(this)->gotoFirstParent()) {
    tmp_item = this->getCurrParent();
  }

  // declare temporary objects
  //
  BiGraphVertex<TObject>* tmp_vert = (BiGraphVertex<TObject>*) NULL;

  // loop over each element and look for the input vertex
  //
  boolean vertex_found = false;
  while ((tmp_item != (BiGraphArc<TObject> *)NULL) &&
	 !vertex_found) {

    // get the vertex out of the node
    //
    tmp_vert = tmp_item->getVertex();

    // check to see if the found vertex is the one we are looking for
    //
    if (tmp_vert == vertex_a) {
      vertex_found = true;
    }
    else {
      if (const_cast<BiGraphVertex<TObject>* >(this)->gotoNextParent()) {
	tmp_item = this->getCurrParent();
      }
      else {
	tmp_item = (BiGraphArc<TObject> *)NULL;
      }
    }
  }

  // restore the saved state
  //
  const_cast<BiGraphVertex<TObject>* >(this)->gotoMarkParent();
  
  // exit gracefully
  //
  return vertex_found;
}

//---------------------------------------------------------------------------
//
// class-specific public methods:
//  vertex comparison methods
//
//---------------------------------------------------------------------------

// method: compareVertices
//
// arguments:
//  const BiGraphVertex<TObject>& compare_vertex: (input) the vertex to compare
//
// return: boolean value indicating test of equivalence
//
// this method compares two vertices for equivalent structure
//
template<class TObject>
boolean BiGraphVertex<TObject>::compareVertices(const BiGraphVertex<TObject>&
						vertex_a) const {

  // declare the output variable
  //
  boolean arc_equal = false;
  
  // check for null items in either vertex
  //
  if (this->item_d == (TObject*)NULL) {
    if (vertex_a.item_d != (TObject*)NULL) {
      return false;
    }
  }
  else if (vertex_a.item_d == (TObject*)NULL) {
    return false;
  }

  // make sure that the vertices have the same number of arcs
  //
  if (this->lengthChild() != vertex_a.lengthChild()) {

      // if the lengths are different then the number of arcs in the
      // vertex are different
      //
      return false;    
  }
  
  // save the current states
  //
  this->setMarkChild();
  vertex_a.setMarkChild();  

  // iterate over all arcs contained in the current vertex
  //
  boolean more_nodes = const_cast< BiGraphVertex<TObject>* >(this)->gotoFirstChild();
    
  while (more_nodes) {

    // get the current arc associated with the vertex
    //
    arc_equal = false;
    BiGraphArc<TObject>* this_arc = const_cast< BiGraphVertex<TObject>* >
      (this)->getCurrChild();

    // iterate over all  arcs associated with the input vertex
    //
    boolean more_nodes1 =
      const_cast< BiGraphVertex<TObject>& >(vertex_a).gotoFirstChild();

    while (more_nodes1) {

      // get the current arc associated with the vertex
      //
      BiGraphArc<TObject>* input_arc = const_cast< BiGraphVertex<TObject>& >
	(vertex_a).getCurrChild();

      // check if the arcs are similar
      //
      if (this_arc->eq(*input_arc)) {
	arc_equal = true;
      }

      // get the next arc in the vertex
      //
      more_nodes1 = const_cast< BiGraphVertex<TObject>& >(vertex_a).gotoNextChild();
    }

    // if none of the arcs in the input vector are similar exit
    //
    if (!arc_equal) {
      const_cast< BiGraphVertex<TObject>* >(this)->gotoMarkChild();
      const_cast< BiGraphVertex<TObject>& >(vertex_a).gotoMarkChild();    
      return false;
    }
    
    // get the next arc in the vertex
    //
    more_nodes = const_cast< BiGraphVertex<TObject>* >(this)->gotoNextChild();
  }
  
  // reset the current pointer and return true
  //
  const_cast< BiGraphVertex<TObject>* >(this)->gotoMarkChild();
  const_cast< BiGraphVertex<TObject>& >(vertex_a).gotoMarkChild();

  // make sure that the vertices have the same number of arcs
  //
  if (this->lengthParent() != vertex_a.lengthParent()) {

      // if the lengths are different then the number of arcs in the
      // vertex are different
      //
      return false;    
  }
  
  // save the current states
  //
  this->setMarkParent();
  vertex_a.setMarkParent();  

  // iterate over all arcs contained in the current vertex
  //
  more_nodes = const_cast< BiGraphVertex<TObject>* >(this)->gotoFirstParent();
    
  while (more_nodes) {

    // get the current arc associated with the vertex
    //
    arc_equal = false;
    BiGraphArc<TObject>* this_arc = const_cast< BiGraphVertex<TObject>* >
      (this)->getCurrParent();

    // iterate over all  arcs associated with the input vertex
    //
    boolean more_nodes1 =
      const_cast< BiGraphVertex<TObject>& >(vertex_a).gotoFirstParent();

    while (more_nodes1) {

      // get the current arc associated with the vertex
      //
      BiGraphArc<TObject>* input_arc = const_cast< BiGraphVertex<TObject>& >
	(vertex_a).getCurrParent();

      // check if the arcs are similar
      //
      if (this_arc->eq(*input_arc)) {
	arc_equal = true;
      }

      // get the next arc in the vertex
      //
      more_nodes1 = const_cast< BiGraphVertex<TObject>& >(vertex_a).gotoNextParent();
    }

    // if none of the arcs in the input vector are similar exit
    //
    if (!arc_equal) {
      const_cast< BiGraphVertex<TObject>* >(this)->gotoMarkParent();
      const_cast< BiGraphVertex<TObject>& >(vertex_a).gotoMarkParent();    
      return false;
    }
    
    // get the next arc in the vertex
    //
    more_nodes = const_cast< BiGraphVertex<TObject>* >(this)->gotoNextParent();
  }
  
  // reset the current pointer and return true
  //
  const_cast< BiGraphVertex<TObject>* >(this)->gotoMarkParent();
  const_cast< BiGraphVertex<TObject>& >(vertex_a).gotoMarkParent();

  // exit gracefully
  //
  return true;
}

// end of include file
//
#endif


