/*
  CoreLinux++ 
  Copyright (C) 1999 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.  
*/   

//
// Implementation of Person. Note the pre and post invariants
// enforcing age changes, as well as the assertion for illegal
// construction or assignment. See notes in header concerning
// real world application which enforces uniqueness in a domain
//

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

#if   !defined(__PERSON_HPP)
#include <Person.hpp>
#endif

using namespace corelinux;

//
// The default (only!) constructor. Note: This is for example
// only. Clearly the fact that we are using a constant string ref
// no way insures that the originating string will be removed from
// the stack without violating our invarience.
//

Person::Person( NameCref aName, Age aAge )
   :
   theName(aName),
   theAge( aAge )
{
   REQUIRE( theName.empty() == false );
   REQUIRE( theAge >= 0 && theAge < Limits::LONGMAX );
}

//
// Illegal constructors defined. You could optionally
// change the assertion to more explicit exceptions
// as shown in the copy constructor
//
Person::Person( void )
   :
   theName(TEXT("")),
   theAge(0)
{
   NEVER_GET_HERE;
}

Person::Person( PersonCref )
   :
   theName(TEXT("")),
   theAge(0)
{
   throw Exception
      (
         TEXT("No two Persons can have the same name in this domain"),
         LOCATION
      );
}

//
// Destructor. With Person there is really nothing to clean up
//

Person::~Person( void )
{
   ;  // do nothing
}

// Operator compares down to the name if applicable

bool  Person::operator==( PersonCref aPerson ) const
{
   bool  isMe(true);

   if( this != &aPerson ||
       this->getName() != aPerson.getName())
   {
      isMe = false;
   }
   else 
   {
      ;  // do nothing
   }

   return isMe;
}

// Illegal operator dealt with

PersonRef Person::operator=( PersonCref )
{
   NEVER_GET_HERE;   // Assignment no allowed
   return *this;     // avoid compiler errors
}

// Explicit name fetch

NameCref Person:: getName( void ) const
{
   return theName;
}

// Coercion name fetch

Person::operator NameCref( void ) const
{
   return theName;
}

// Explicit age fetch

AgeCref Person:: getAge( void ) const
{
   return theAge;
}

// Coercion age fetch

Person::operator AgeCref( void ) const
{
   return theAge;
}

//
// Here we can change the age while at
// the same time showing a good practice,
// mainly INSURING THAT THE STATE OF THE
// PERSON IS PRESERVED!!! Another note
// is that the assertions from Assertion.hpp
// can be compiled away. It is up to the
// developer to understand what type constraints
// should live forever, or just during development.
//

void  Person::setAge( Age aAge )
{
   REQUIRE( aAge >= 0 );

   // Copy for restore

   Age   aTempAge(this->getAge());

   theAge = aAge;

   try
   {
      ENSURE( theAge < Limits::LONGMAX );
   }
   catch( AssertionRef e )
   {
      theAge = aTempAge;
      throw;
   }
}

/*
   Common rcs information do not modify
   $Author: frankc $
   $Revision: 1.3 $
   $Date: 2000/01/19 14:30:07 $
   $Locker:  $
*/

