/******************************************************************************
FILE:               BpClass.cc
LANGUAGE:           C++
SYSTEM:             None
USER-INTERFACE:     None
DESCRIPTION
    This is the implementation of the BpClass class.
    This class represent the BpObject sub*-classes at runtime.
    The current implementation only implements the inheritance hierarchy,
    and may be used to dynamically check membership or kindship, or to
    dynamically intanciate these classes.
    The use of this class outdates the need for the className() method that
    needed to be overridden by sub*-classes of BpObject, but needs the
    overriding of the makeBrother method.
AUTHORS
    <PJB> Pascal J. Bourguignon
MODIFICATIONS
    Revision 1.1  2001/06/05 06:38:19  uid1006
    Added common libraries and dosname utility to the repository.

    Revision 1.4  1995/11/30 10:31:44  pascal
    Fix apres fusion avec les objets developpes par ERS

    Revision 1.3  95/11/24  16:13:02  pascal
    Added retain/release for isa.

    Revision 1.2  95/11/24  14:24:34  pascal
    Corrected constructor; added friend proc BpClass_CreateMetaClasses in
    BpClass.

    Revision 1.1  95/11/19  11:14:01  pascal
    Initial revision

    1995-11-19 <PJB> Creation.
LEGAL
    Copyright Pascal J. Bourguignon 1995 - 2011

    This file is part of the bplib library..

    This  program is  free software;  you can  redistribute  it and/or
    modify it  under the  terms of the  GNU General Public  License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.

    This program  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
    General Public License for more details.

    You should have received a  copy of the GNU General Public License
    along with  this program; see the  file COPYING; if  not, write to
    the Free  Software Foundation, Inc.,  59 Temple Place,  Suite 330,
    Boston, MA 02111-1307 USA
******************************************************************************/
#include <names.h>
#include BpClass_hh
#include BcImplementation_h

static const char rcsid[]="$Id";

// birth and death:

/*
  The instances must retain their isa BpClass.
  The BpClasses retains their superclass and their factory.
  As a instance, the factories retain their isa BpClass. This set
  up a loop in the retain dependancy that prevent the BpClasses to
  be freed. This is intentional.
*/

static BpClass* BpClassClass=NIL;

PROCEDURE(BpClass_CreateMetaClasses,(void),BpClass*)
{
    BpClass*        objectClass;

    objectClass=NEW(BpClass);
    BpClassClass=NEW(BpClass);

    if(objectClass->isa!=NIL){  // this should not happen.
        objectClass->isa->release();
    }
    objectClass->isa=BpClassClass;
    objectClass->isa->retain();
    objectClass->superClassSet(objectClass);

    if(BpClassClass->isa!=NIL){ // this should not happen.
        BpClassClass->isa->release();
    }
    BpClassClass->isa=BpClassClass;
    BpClassClass->isa->retain();
    BpClassClass->superClassSet(objectClass);

    BpClassClass->nameSet("BpClass");
    BpClassClass->factorySet(BpClassClass);

    return(objectClass);
}//BpClass_CreateMetaClasses;

CLASSMETHOD(BpClass,createMetaClasses,(void),BpClass*)
{
    return(BpClass_CreateMetaClasses());
}

CONSTRUCTOR(BpClass)
{
    // No BpClass_PLUG here: it's done by BpClass_CreateMetaClasses,
    // called by BpObject constructor.
    if((isa!=NIL)&&(isa!=(BpClass*)1)){
        isa->release();
    }
    isa=BpClassClass;
    if(isa!=NIL){
        isa->retain();
    }
    fName=NIL;
    fSuperClass=NIL;
    fFactory=NIL;
}//BpClass;


DESTRUCTOR(BpClass)
{
    if(fFactory!=NIL){
        fFactory->release();
    }
    if(fSuperClass!=NIL){
        fSuperClass->release();
    }
}//~BpClass;


METHOD(BpClass,nameSet,(const char* nName),void)
{
    fName=nName;
}//nameSet;


METHOD(BpClass,superClassSet,(BpClass* nSuper),void)
{
    if(fSuperClass!=NIL){
        fSuperClass->release();
    }
    fSuperClass=nSuper;
    fSuperClass->retain();
}//superClassSet;


METHOD(BpClass,factorySet,(BpObject* nFactory),void)
{
    if(fFactory!=NIL){
        fFactory->release();
    }
    fFactory=nFactory;
    fFactory->retain();
}//factorySet;


// override of BpObject methods:

METHOD(BpClass,makeBrother,(void),BpObject*)
{
    return(NEW(BpClass));
}//makeBrother;


METHOD(BpClass,printOnLevel,(FILE* file,CARD32 level),void)
{
    BpClass_SUPER::printOnLevel(file,level);
    PRINTONLEVEL(file,level,"%s",fName,fName);
    PRINTONLEVEL(file,level,"%p",fSuperClass,fSuperClass);
    PRINTONLEVEL(file,level,"%p",fFactory,fFactory);
}//printOnLevel;


// BpClass methods:

METHOD(BpClass,name,(void),const char*)
{
    return(fName);
}//name;


METHOD(BpClass,superClass,(void),BpClass*)
{
    if(fSuperClass==NIL){
        return(this);
    }else{
        return(fSuperClass);
    }
}//superClass;


METHOD(BpClass,factory,(void),BpObject*)
{
    return(fFactory);
}//factory;


METHOD(BpClass,makeInstance,(void),BpObject*)
{
    return(fFactory->makeBrother());
}//makeInstance;


METHOD(BpClass,isSubClassOf,(BpClass* aClass),BOOLEAN)
{
    BpClass*    current;
    BpClass*    next;

    current=this;
    next=current->superClass();
    while((current!=next)&&(current!=aClass)){
        current=next;
        next=current->superClass();
    }
    return(current==aClass);
}//isSubClassOf;



PROCEDURE(BpClass_classNamed,(const char* className),BpClass*)
{
    // SEE: BpClass_classNamed is not implemented.
    /*
      We should use our own hashtable.
    */
    return(NIL);
}//BpClass_classNamed;


//END BpClass.
ViewGit