/*
  CoreLinux++ 
  Copyright (C) 2000 CoreLinux Consortium
  
   The CoreLinux++ Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The CoreLinux++ Library Library is distributed in the hope that it will 
   be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  
*/   

#if   !defined(__COMMON_HPP)
#include <Common.hpp>
#endif

#if   !defined(__MODELER_HPP)
#include <Modeler.hpp>
#endif

using namespace corelinux;

//
// Default Constructor
//

Modeler::Modeler( void )
{
   ;  // do nothing
}

//
// Copy constructor
//

Modeler::Modeler( ModelerCref aRef )
   :
   theParentsMap( aRef.theParentsMap )
{
   ;  // do nothing
}

//
// Destructor
//

Modeler::~Modeler( void )
{
   IdMapIterator  begin( theParentsMap.begin() );
   IdMapIterator  end( theParentsMap.end() );

   while( begin != end )
   {
      (*begin).second.clear();
      ++begin;
   }

   theParentsMap.clear();
}

//
// Assignment operator
//

ModelerRef Modeler::operator=( ModelerCref aRef )
{
   theParentsMap =  aRef.theParentsMap;
   return (*this);
}

//
// Equality operator
//

bool Modeler::operator==( ModelerCref aRef ) const
{
   return (this == &aRef );
}

Count Modeler::getParentCount( DwordIdentifierCref aId ) const
{
   Count aCount(0);
   IdMapConstIterator fItr( theParentsMap.find(aId) );
   if( fItr != theParentsMap.end() )
   {
      aCount = (*fItr).second.size();
   }
   else
   {
      ;  // do nothing
   }

   return aCount;
}

IdVector Modeler::getParents( DwordIdentifierCref aId ) const
                                 throw(Exception) 
{
   IdVector             aVector;
   IdMapConstIterator   fItr( theParentsMap.find(aId) );

   if( fItr == theParentsMap.end() )
   {
      throw Exception("Id has no parents",LOCATION);
   }
   else
   {
      aVector = (*fItr).second;
   }

   return aVector;
}

//
// Add a parent to a element
//

void  Modeler::addParent( DwordIdentifierCref aId, DwordIdentifierCref aParent )
{
   IdMapIterator   fItr( theParentsMap.find(aId) );

   if( fItr != theParentsMap.end() )
   {
      (*fItr).second.push_back(aParent);
   }
   else
   {
      IdVector aVec;

      aVec.push_back(aParent);
      theParentsMap[aId] = aVec;  
   }

}

//
// Remove a parent from a element
//

void  Modeler::removeParent( DwordIdentifierCref aId, DwordIdentifierCref aParent )
{
   IdMapIterator   fItr( theParentsMap.find(aId) );

   if( fItr != theParentsMap.end() )
   {
      IdVectorIterator  begin( (*fItr).second.begin() );
      IdVectorIterator  end( (*fItr).second.end() );

      while( begin != end )
      {
         if( (*begin) == aParent )
         {
            (*fItr).second.erase(begin);
            begin = end;
         }
         else
         {
            ++begin;
         }
      }

      if( (*fItr).second.size() == 0 )
      {
         theParentsMap.erase(fItr);
      }
      else
      {
         ;  // do nothing
      }
   }
   else
   {
      ;  // do nothing
   }

}

//
// Remove all parents from a element
//

void  Modeler::removeParents( DwordIdentifierCref aId )
{
   IdMapIterator   fItr( theParentsMap.find(aId) );
   if( fItr != theParentsMap.end() )
   {
      (*fItr).second.clear();
      theParentsMap.erase(fItr);
   }
   else
   {
      ;  // do nothing
   }

}

//
// Find where I am a parent, and remove me from
// those lists
//

void  Modeler::removeChildren( DwordIdentifierCref aId )
{
   IdMapIterator  begin( theParentsMap.begin() );
   IdMapIterator  end( theParentsMap.end() );
   IdVector       aList;

   //
   // Searh the child to parent list
   //

   while( begin != end )
   {

      IdVectorIterator  ibegin( (*begin).second.begin() );
      IdVectorIterator  iend( (*begin).second.end() );

      //
      // Look for me in the parent list
      //

      while( ibegin != iend )
      {
         //
         // Note my children
         //

         if( (*ibegin) == aId )
         {
            aList.push_back((*begin).first);
            ibegin = iend;
         }
         else
         {
            ++ibegin;
         }
      }
      ++begin;
   }

   //
   // If I am a parent to any then get
   // myself removed
   //

   if( aList.size() != 0 )
   {
      IdVectorIterator  ibegin( aList.begin() );
      IdVectorIterator  iend( aList.end() );
      while( ibegin != iend )
      {
         this->removeParent( (*ibegin), aId );
         ++ibegin;
      }

      aList.clear();
   }

}


/*
   Common rcs information do not modify
   $Author: frankc $
   $Revision: 1.2 $
   $Date: 2000/03/01 03:28:18 $
   $Locker:  $
*/


