3D PLM Enterprise Architecture

Middleware Abstraction - Object Modeler

Creating Components

Making objects that implement interfaces
Use Case

Abstract

This article shows how to create CAA V5 components.


What You Will Learn With This Use Case

This use case is intended to show you how to create CAA V5 components [1], that is, how to bundle several C++ classes that each implements one or several interfaces [2] and make that this set of classes acts and behaves as a single application object.

[Top]

The CAASysGeoModelImpl Use Case

CAASysGeoModelImpl is a use case of the CAASystem.edu framework that illustrates the System framework capabilities.

[Top]

What Does CAASysGeoModelImpl Do

This use case includes the code for a set of components that stand for geometric objects. The circle is taken as example.

The circle component is made of the CAASysCircle main class, and of the CAAESysCreateInstanceForCircle, CAAESysCircle, CAAESysCircleCenterProperties, and CAAESysColorProperties extension classes. CAAESysCreateInstanceForCircle implements the CATICreateInstance interface to enable the component creation. CAAESysCircle implements the CAAISysCircle interface that is the circle type interface. CAAESysCircleCenterProperties implements the CAAISysCircleCenterProperties interface to manage the marker used to represent the circle center. CAAESysColorProperties implements the CAAISysColorProperties interface to manage the circle color. CAAESysCircle and CAAISysCircleCenterProperties are extension classes of the CAASysCircle class only, while CAAESysColorProperties is shared with other geometric components, such as the line, the polyline, and the ellipse. Refer to sharing extensions in [1].

In addition, the factory for the circle component is also described. The CAASysGeomCont main class that represents a container for geometric objects implements the CAAISysGeomFactory interface through a code extension class named CAAESysGeomFactoryForGeomCont [3].

Note: Extension links are shown as dashed arrows, and implementation to interface links are shown using the realization link symbol, made of a dash line ended using a triangle on the interface side.

[Top]

How to Launch CAASysGeoModelImpl

You first need to build CAASysGeoModelImpl. To do this, you will need to set up the build time environment, then compile CAASysGeoModelImpl along with its prerequisites as described in [5]. You cannot launch CAASysGeoModelImpl itself. CAASysGeoModelImpl is simply used by the CAASysUsingComp [4] use case.

[Top]

Where to Find the CAASysGeoModelImpl Code

The CAASysGeoModelImpl use case is made of several classes located in the CAASysGeoModelComp.m for the component main classes and extension classes that implement CATICreateInstance, and CAASysGeoModelImpl.m module for the other extension classes. These modules belong to the CAASystem.edu framework:

Windows InstallRootDirectory\CAASystem.edu\
Unix InstallRootDirectory/CAASystem.edu/

where InstallRootDirectory is the directory where the CAA CD-ROM is installed. The header files of shared classes are located in the PrivateInterfaces directory of CAASystem.edu.

[Top]

Step-by-Step

To create a component such as CAASysCircle, there are nine main steps:

# Step Where
1 Create the CAASysCircle component main class header file ProtectedInterfaces\CAASysCircle.h
2 Create the CAASysCircle component main class source file CAASysGeoModelComp.m\src\CAASysCircle.cpp
3 Create the CAAESysCreateInstanceForCircle extension class header file CAASysGeoModelComp.m\LocaInterfaces\CAAESysCreateInstanceForCircle.h
4 Create the CAAESysCreateInstanceForCircle extension class source file CAASysGeoModelComp.m\src\CAAESysCreateInstanceForCircle.cpp
5 Create the CAAESysCircle extension class header file CAAESysCircle.h file
6 Create the CAAESysCircle extension class source file CAAESysCircle.cpp file
7 Create the CAAESysCenterProperties extension class header file CAAESysCircleCenterProperties.h file
8 Create the CAAESysCenterProperties extension class source file CAAESysCircleCenterProperties.cpp file
9 Create the CAAESysColorProperties shared extension class header file CAAESysColorProperties.h file
10 Create the CAAESysColorProperties shared extension class source file CAAESysColorProperties.cpp file
11 Update the interface dictionary CAASystem.edu.dico file

[Top]

Creating the CAASysCircle Header File

#include "CATBaseUnknown.h"     //Needed to derive from CATBaseUnknown
#include "CAASysGeoModelComp.h" //To export the class 

class ExportedByCAASysGeoModelComp CAASysCircle : public CATBaseUnknown
{
  CATDeclareClass;
  public:
    CAASysCircle();
    virtual ~CAASysCircle();
  private:
    CAASysCircle(const CAASysCircle &iObjectToCopy);

The CAASysCircle class C++-derives from CATBaseUnknown. The CATDeclareClass macro declares that the class CAASysCircle belongs to a component. Note that the copy constructor is set as private. The class has a constructor and a destructor only.

[Top]

Creating the CAASysCircle Source File

#include "CAASysCircle.h"

CATImplementClass(CAASysCircle, Implementation, CATBaseUnknown, CATNull);

CAASysCircle::CAASysCircle()  {}

CAASysCircle::~CAASysCircle() {}

The CATImplementClass macro declares that the CAASysCircle class is a component main class thanks the Implementation keyword, and OM-derives [6] from CATBaseUnknown. Any component main class declared as an Implementation must C++-derive and OM-derive from the same class, that must either be CATBaseUnknown or another component main class. The component main class doesn't implement any interface, but it could.

[Top]

Creating the CAAESysCreateInstanceForCircle Extension Class Header File

#include "CATBaseUnknown.h"   //Needed to derive from CATBaseUnknown

class CAAESysCreateInstanceForCircle : public CATBaseUnknown
{
  CATDeclareClass;
  public:
    CAAESysCreateInstanceForCircle();
    virtual ~CAAESysCreateInstanceForCircle();
    virtual HRESULT __stdcall CreateInstance(void **oppv);

  private:
    CAAESysCreateInstanceForCircle(const CAAESysCreateInstanceForCircle &iObjectToCopy);
};

The CAAESysCreateInstanceForCircle extension class derives from CATBaseUnknown. The CATDeclareClass macro declares that the class CAAESysCreateInstanceForCircle belongs to a component. The class has a constructor and a destructor, and declares the CreateInstance method which is the only method of the CATICreateInstance interface. Note that the copy constructor is set as private. This is very important for extensions. Since extensions must never be directly instantiated by client applications, this prevents the compiler from creating the copy constructor as public without you know. This copy constructor is not implemented in the source file.

[Top]

Creating the CAAESysCircle Extension Class Source File

#include "CAAESysCreateInstanceForCircle.h"
#include "CAASysCircle.h"
#include <CATErrorDef.h>

#include "TIE_CATICreateInstance.h"
TIE_CATICreateInstance(CAAESysCreateInstanceForCircle);

CATImplementClass(CAAESysCreateInstanceForCircle, CodeExtension, CATBaseUnknown, CAASysCircle);

CAAESysCreateInstanceForCircle::CAAESysCreateInstanceForCircle()  {}

CAAESysCreateInstanceForCircle::~CAAESysCreateInstanceForCircle() {}

HRESULT __stdcall CAAESysCreateInstanceForCircle::CreateInstance(void ** oppv)
{
   CAASysCircle * pt = new CAASysCircle();
   if (NULL == pt) return(E_OUTOFMEMORY);
   *oppv = (void *)pt;
   return(S_OK);
}

The CAAESysCreateInstanceForCircle class states that it implements the CATICreatInstance interface thanks to the TIE_CATICreateInsatnce macro. This extension class is dedicated to the circle component, and the CATImplementClass macro declares that the CAAESysCreateInstanceForCircle class is code extension class, thanks to the CodeExtension keyword, and that it extends the component whose main class is CAASysCircle. The third parameter must always be set to CATBaseUnknown, makes no sense, and is unused for extensions. The CreateInstance method instantiates the CAASysCircle component main class. This method is called by the CATInstantiateComponent global function that is used by client applications to instantiate the component [4].

[Top]

Creating the CAAESysCircle Extension Class Header File

#include "CATBaseUnknown.h"   //Needed to derive from CATBaseUnknown

// Mathematics Framework
#include "CATMathPoint.h"     //Needed by SetCenter & GetCenter
#include "CATMathVector.h"    //Needed by SetPlanar & GetPlanar

class CAAESysCircle : public CATBaseUnknown
{
  CATDeclareClass;
  public:
    CAAESysCircle();
    virtual ~CAAESysCircle();
    // CAAISysCircle interface methods
    virtual  HRESULT  SetCenter(const CATMathPoint  & iCenter) ;
    virtual  HRESULT  GetCenter(CATMathPoint        & oCenter) const ;
    virtual  HRESULT  SetRadius(const float           iRadius) ;
    virtual  HRESULT  GetRadius(float               & oRadius) const ;
    virtual  HRESULT  SetPlane (const CATMathVector & iNormal ,
                                const CATMathVector & iAxis );
    virtual  HRESULT  GetPlane (CATMathVector       & oNormal ,
                                CATMathVector       & oAxis  ) const;    
  private:
    CAAESysCircle(const CAAESysCircle &iObjectToCopy);
  private:
    float           _Radius ;
    CATMathPoint    _Center ;
    CATMathVector   _Normal ;
    CATMathVector   _Axis ;
};

The CAAESysCircle extension class derives from CATBaseUnknown. The CATDeclareClass macro declares that the class CAAESysCircle belongs to a component. The class has a constructor and a destructor, and declares the methods of the CAAISysCircle interface, that set and get the circle center, radius, and plane. Note that the copy constructor is set as private. This is very important for extensions. Since extensions must never be directly instantiated by client applications, this prevents the compiler from creating the copy constructor as public without you know. This copy constructor is not implemented in the source file. The circle data are its center, its radius, the normal to its plane, and an axis of this plane.

[Top]

Creating the CAAESysCircle Extension Class Source File

#include "CAAESysCircle.h"

#include "TIE_CAAISysCircle.h"
TIE_CAAISysCircle(CAAESysCircle);

CATImplementClass(CAAESysCircle, DataExtension, CATBaseUnknown, CAASysCircle);

CAAESysCircle::CAAESysCircle() : _Radius(0) {}

CAAESysCircle::~CAAESysCircle() {}

HRESULT  CAAESysCircle::SetCenter(const CATMathPoint & iCenter) 
{
  _Center = iCenter ;
  return S_OK;
}

HRESULT  CAAESysCircle::SetRadius(const float iRadius) 
{
  _Radius = iRadius ;
  return S_OK;
}
	
HRESULT  CAAESysCircle::SetPlanar(const CATMathVector & iNormal, 
                                  const CATMathVector & iAxis) 
{
  _Normal= iNormal ;
  _Axis = iAxis ;
  return S_OK;
}
 
HRESULT CAAESysCircle::GetCenter(CATMathPoint & oCenter) const 
{
  oCenter = _Center ;
  return S_OK;
}
	
HRESULT CAAESysCircle::GetRadius(float & oRadius) const
{
  oRadius = _Radius ;
  return S_OK;
}
	
HRESULT  CAAESysCircle::GetPlanar(CATMathVector & oNormal ,
                                  CATMathVector & oAxis) const
{
  oNormal = _Normal ;
  oAxis   = _Axis ;  
  return S_OK;
}

The CAAESysCircle class states that it implements the CAAISysCircle interface thanks to the TIE_CAAISysCircle macro. This extension class is dedicated to the circle component, and the CATImplementClass macro declares that the CAAESysCircle class is data extension class, thanks to the DataExtension keyword, and that it extends the component whose main class is CAASysCircle. The third parameter must always be set to CATBaseUnknown, makes no sense, and is unused for extensions. The CAAISysCircle interface methods are implemented as usual.

[Top]

Creating the CAAESysCircleCenterProperties Extension Class Header File

#include "CATBaseUnknown.h"                // Needed to derive from  CATBaseUnknown
#include "CAAISysCircleCenterProperties.h" // Needed to have the marker type

class CAAESysCircleCenterProperties: public CATBaseUnknown
{
  CATDeclareClass;
  public:
    CAAESysCircleCenterProperties();
    virtual ~CAAESysCircleCenterProperties();

    virtual HRESULT GetMarkerType(CAAISysCircleCenterProperties::MarkerType & oMarkerType);
    virtual HRESULT SetMarkerType(const CAAISysCircleCenterProperties::MarkerType iMarkerType);
  private:
    CAAESysCircleCenterProperties(const CAAESysCircleCenterProperties &iObjectToCopy);
  private:
    CAAISysCircleCenterProperties::MarkerType _MarkerType ;
};

The CAAESysCircleCenterProperties extension class derives from CATBaseUnknown. The CATDeclareClass macro declares that the class CAACAAESysCircleCenterProperties belongs to a component. The class has a constructor and a destructor, and declares the GetMarkerType and SetMarkerType methods of the CAAISysCircleCenterProperties interface. The marker type is set as a private data member. Note that the copy constructor is set as private. This is very important for extensions. Since extensions must never be directly instantiated by client applications, this prevents the compiler from creating the copy constructor as public without you know. This copy constructor is not implemented in the source file.

[Top]

Creating the CAAESysCircleCenterProperties Extension Class Source File

#include "CAAESysCircleCenterProperties.h"

#include "TIE_CAAISysCircleCenterProperties.h"
TIE_CAAISysCircleCenterProperties(CAAESysCircleCenterProperties);

CATImplementClass(CAAESysCircleCenterProperties, DataExtension, CATBaseUnknown, CAASysCircle);

CAAESysCircleCenterProperties::CAAESysCircleCenterProperties(): 
               _MarkerType(CAAISysCircleCenterProperties::Dot)
{}

CAAESysCircleCenterProperties::~CAAESysCircleCenterProperties()
{}

HRESULT CAAESysCircleCenterProperties::GetMarkerType(CAAISysCircleCenterProperties::MarkerType & oMarkerType )
{
  oMarkerType = _MarkerType ;
  return (S_OK);
}

HRESULT CAAESysCircleCenterProperties::SetMarkerType(const CAAISysCircleCenterProperties::MarkerType iMarkerType)
{
  _MarkerType = iMarkerType ;
  return (S_OK);
}

The CAAESysColorProperties class states that it implements the CAAISysPointProperties interface thanks to the TIE_CAAISysPointProperties macro. This extension class is dedicated to the circle components, and the CATImplementClass macro declares that the CAAESysPointProperties class is data extension class, thanks to the DataExtension keyword, and that it extends the component whose main class is CAASysCircle. The third parameter must always be set to CATBaseUnknown, makes no sense, and is unused for extensions. The CAAISysPointProperties interface methods are implemented as usual.

[Top]

Creating the CAAEColorProperties Shared Extension Class Header File

#include "CATBaseUnknown.h"   // to derive from  CATBaseUnknown

class CAAESysColorProperties: public CATBaseUnknown
{
  // Used in conjunction with CATImplementClass in the .cpp file
  CATDeclareClass;

  public:
    CAAESysColorProperties();
    virtual ~CAAESysColorProperties();

    virtual HRESULT GetColor(      int &oRed,       int &oGreen,       int &oBlue) const;
    virtual HRESULT SetColor(const int  iRed, const int  iGreen, const int  iBlue); 

  private:
    CAAESysColorProperties(const CAAESysColorProperties &iObjectToCopy);
  private:
    int _Red, _Green, _Blue,;
};

The CAAESysColorProperties extension class derives from CATBaseUnknown. The CATDeclareClass macro declares that the class CAAESysColorProperties belongs to a component. The class has a constructor and a destructor, and declares the GetColor and SetColor methods of the CAAISysColorProperties interface. The RGB color components are set as private data members. Note that the copy constructor is set as private. This is very important for extensions. Since extensions must never be directly instantiated by client applications, this prevents the compiler from creating the copy constructor as public. This copy constructor is not implemented in the source file.

[Top]

Creating the CAAEColorProperties Shared Extension Class Source File

#include "CAAESysColorProperties.h"

#include "TIE_CAAISysColorProperties.h"
TIE_CAAISysColorProperties(CAAESysColorProperties);

CATBeginImplementClass(CAAESysColorProperties, DataExtension, CATBaseUnknown, CAASysCircle);
CATAddClassExtension(CAASysEllipse) ;
CATAddClassExtension(CAASysLine) ;
CATAddClassExtension(CAASysPolyline) ;
CATEndImplementClass(CAAESysColorProperties);

CAAESysColorProperties::CAAESysColorProperties()
                      : _Red(255),_Blue(255),_Green(255)
{}

CAAESysColorProperties::~CAAESysColorProperties() {}

HRESULT CAAESysColorProperties::SetColor(const int iRed, const int iGreen, const int iBlue) 
{
    if ( (iRed   < 0) || (iRed   > 255) ) return E_FAIL;
    if ( (iGreen < 0) || (iGreen > 255) ) return E_FAIL;
    if ( (iBlue  < 0) || (iBlue  > 255) ) return E_FAIL;

    _Red   = iRed ;
    _Green = iGreen ;
    _Blue  = iBlue ;

    return (S_OK);
}

HRESULT CAAESysColorProperties::GetColor(int & oRed, int & oGreen, int & oBlue) const
{
    oRed   = _Red;
    oGreen = _Green;
    oBlue  = _Blue;

    return (S_OK);
}

The CAAESysColorProperties class states that it implements the CAAISysColorProperties interface thanks to the TIE_CAAISysColorProperties macro. This extension class is shared by several components, and declares these components thanks to the CATBeginImplementClass, CATAddClassExtension, and CATEndImplementClass macros:

The CAAISysColorProperties interface methods are implemented as usual.

[Top]

Updating the Interface Dictionary

...
CAASysCircle CATICreateInstance            libCAASysGeoModelComp
CAASysCircle CAAISysCircle                 libCAASysGeoModelImpl
CAASysCircle CAAISysColorProperties        libCAASysGeoModelImpl
CAASysCircle CAAISysCircleCenterProperties libCAASysGeoModelImpl
...

The interface dictionary declares that the CAASysCircle component implements the CAAISysCircle, CAAISysColorProperties, and CAAISysCircleCenterProperties, and that the code to load into memory to use these interfaces is located in the libCAASysGeoModelImpl shared library or DLL. Note that the component main class name is used to refer to the component in the interface dictionary, and never the extension class names. Note also that the shared library or DLL to associate with the component/interface pair is the one that contains the code created by the call to the TIE macro (This is generally the same library than the one that contains the interface implementation code, since the TIE macro is usually included in the extension class source file.) This is because when a client asks a component for an interface pointer, the TIE class is instantiated first, and it either retrieves the existing instance of the appropriate extension class, or otherwise instantiates it.

Top]


In Short

This use case shows how to create a component using a main class and extension classes. The main class declares the component inheritance and must C++-derive and OM-derive from CATBaseUnknown or from another component main class. Extension classes must directly or indirectly C++-derive from CATBaseUnknown, while OM-inheritance makes no sense for them. An extension class can be dedicated to a component or shared by several components. The interface dictionary declares the correspondence between the component, the interfaces it implements, and the shared library or DLL to load for each interface.

[Top]


References

[1] Creating Components
[2] Creating Interfaces
[3] Creating a Component Factory
[4] Using Components
[5] Building and Launching a CAA V5 Use Case
[6] Object Modeler Component and Implementation Inheritances
[Top]

History

Version: 1 [Mar 2000] Document created
[Top]

Copyright © 2000, Dassault Systèmes. All rights reserved.