#ifndef _Standard_DefineHandle_HeaderFile
#define _Standard_DefineHandle_HeaderFile

class Standard_Transient;
class Standard_Persistent;
class Handle_Standard_Type;

// TRANSIENT
//
#define DEFINE_STANDARD_HANDLE(C1,C2) \
class C1; \
Standard_EXPORT Handle_Standard_Type& C1##_Type_(); \
 \
class Handle_##C1 : public Handle_##C2 { \
  public: \
    Handle_##C1():Handle_##C2() {}  \
    Handle_##C1(const Handle_##C1& aHandle) : Handle_##C2(aHandle)  \
     { \
     } \
 \
    Handle_##C1(const C1* anItem) : Handle_##C2((C2 *)anItem)  \
     { \
     } \
 \
    Handle_##C1& operator=(const Handle_##C1& aHandle) \
     { \
      Assign(aHandle.Access()); \
      return *this; \
     } \
 \
    Handle_##C1& operator=(const C1* anItem) \
     { \
      Assign((Standard_Transient *)anItem); \
      return *this; \
     } \
 \
    C1* operator->() const  \
     { \
      return (C1 *)ControlAccess(); \
     } \
  \
    Standard_EXPORT static const Handle_##C1 DownCast(const Handle(Standard_Transient)& AnObject); \
};

#define IMPLEMENT_STANDARD_HANDLE(C1,C2) \
const Handle_##C1 Handle_##C1::DownCast(const Handle(Standard_Transient)& AnObject)  \
{ \
  Handle_##C1 _anOtherObject; \
 \
  if (!AnObject.IsNull()) { \
     if (AnObject->IsKind(C1##_Type_())) { \
       _anOtherObject = Handle_##C1((Handle_##C1&)AnObject); \
     } \
  } \
 \
  return _anOtherObject ; \
}

// PERSISTENT
//
#define DEFINE_STANDARD_PHANDLE(C1,C2) \
class C1; \
Standard_EXPORT Handle_Standard_Type& C1##_Type_(); \
 \
class Handle_##C1 : public Handle_##C2 { \
  public: \
    Handle_##C1():Handle_##C2() {}  \
    Handle_##C1(const Handle_##C1& aHandle) : Handle_##C2(aHandle)  \
     { \
     } \
 \
    Handle_##C1(const C1* anItem) : Handle_##C2((C2 *)anItem)  \
     { \
     } \
 \
    Handle_##C1& operator=(const Handle_##C1& aHandle) \
     { \
      Assign(aHandle.Access()); \
      return *this; \
     } \
 \
    Handle_##C1& operator=(const C1* anItem) \
     { \
      Assign((Standard_Persistent *)anItem); \
      return *this; \
     } \
 \
    C1* operator->() const  \
     { \
      return (C1 *)ControlAccess(); \
     } \
  \
    Standard_EXPORT static const Handle_##C1 DownCast(const Handle(Standard_Persistent)& AnObject); \
};

#define IMPLEMENT_STANDARD_PHANDLE(C1,C2) \
const Handle_##C1 Handle_##C1::DownCast(const Handle(Standard_Persistent)& AnObject)  \
{ \
  Handle_##C1 _anOtherObject; \
 \
  if (!AnObject.IsNull()) { \
     if (AnObject->IsKind(C1##_Type_())) { \
       _anOtherObject = Handle_##C1((Handle_##C1&)AnObject); \
     } \
  } \
 \
  return _anOtherObject ; \
}

// GESTION DE TYPE
//
#define DEFINE_STANDARD_RTTI(C1) \
 Standard_EXPORT const Handle(Standard_Type)& DynamicType() const; 

#define IMPLEMENT_STANDARD_RTTI(C1,C2) \
const Handle_Standard_Type& C1::DynamicType() const  \
{  \
	return C1##_Type_();  \
}

#define IMPLEMENT_STANDARD_TYPE(C1) \
Handle_Standard_Type& C1##_Type_() {

#define IMPLEMENT_STANDARD_SUPERTYPE(C1) \
  static Handle_Standard_Type aType##C1 = C1##_Type_();

#define IMPLEMENT_STANDARD_SUPERTYPE_ARRAY() \
  static Handle_Standard_Transient _Ancestors[]= {
	
#define IMPLEMENT_STANDARD_SUPERTYPE_ARRAY_ENTRY(C1) \
    aType##C1,

#define IMPLEMENT_STANDARD_SUPERTYPE_ARRAY_END() \
    NULL \
  };

#define IMPLEMENT_STANDARD_TYPE_END(C1) \
  static Handle_Standard_Type _aType = new Standard_Type(#C1,sizeof(C1),1, \
			                                 (Standard_Address)_Ancestors, \
			                                 (Standard_Address)NULL); \
  return _aType; \
}

#define IMPLEMENT_STANDARD_RTTIEXT(C1,C2) \
   const Handle_Standard_Type& C1::DynamicType() const  \
   {  \
         return C1##_Type_();  \
   } \
   \
   Handle_Standard_Type& C1##_Type_() { \
     static Handle_Standard_Type aType##C2 = C2##_Type_();\
     static Handle_Standard_Transient _Ancestors[]= {aType##C2,NULL}; \
     static Handle_Standard_Type _aType = new Standard_Type(#C1,sizeof(C1),1, \
			                                 (Standard_Address)_Ancestors, \
			                                 (Standard_Address)NULL); \
     return _aType; \
   }

#endif
