PPR Hub |
Product Modeler |
Creating New Features "From Scratch" in a Product DocumentInstantiating new features in applicative containers |
Use Case | ||
CAAPstIntegrateNewFeatures > CAAPstINFBuildCatalog > CAAPstINFCreateDocument > CAAPstINFInitCont > CAAPstINFNavigate > CAAPstINFVisu > CAAPstINFGraphicalProperties > CAAPstINFEdit > CAAPstINFCCP > CAAPstINFDelete > CAAPstINFUpdate |
AbstractThis article discusses the CAAPstINFCreateDocument use case. This use case explains how to create a new applicative container in a Product document and how to instantiate new features in it. |
This use case is intended to illustrate how to instantiate new features in an applicative container of a Product document.
You should already be familiar with the CAAPstIntegrateNewFeatures use case article [1] in order to more easily understand the context of this use case. A general pre-requisite knowledge of the Feature Modeler and of Providers may be required to fully understand this sample. You may want to review the basics of the Feature Modeler by looking over the "Feature Modeler Overview" technical article [2]. Finally, it may be useful for you to look over the "Product Structure Model" technical article [3] as well.
[Top]
The CAAPstINFCreateDocument is a use case that is part of the CAAPstIntegrateNewFeatures use case defined in the CAAProductStructure.edu framework that illustrates the integration of ObjectSpecsModeler framework capabilities in the scope of a Product document.
[Top]
This use case is made up of a batch program that creates a new Product document, a new applicative container within the Product document and a number of new features within the applicative container. The StartUps of these features were created by the CAAPstINFBuildCatalog use case [4]. Each new feature type implements its own interface whose methods manage the valuation and retrieval of the feature's attributes. These implementations will be looked at in detail in this use case as well.
Initially, the Product document is created and the "CAAPstINFCont" applicative container is created within it. Next, two "CAAPstINFRoot" features are instantiated in the applicative container, the first that will aggregate the other features and the second that will be used during the interactive scenario to demonstrate CCP capabilities. Five "CAAPstINFPoint" features are then instantiated in the applicative container, each having different coordinate values. Then, a "CAAPstINFLine" feature is also instantiated, whose attribute values reference the first two "CAAPstINFPoint" features. Finally, a "CAAPstINFWire" feature is instantiated and its attribute points to a list containing references to the last three "CAAPstINFPoint" features. The "CAAPstINFPoint", "CAAPstINFLine" and "CAAPstINFWire" features are then aggregated by the first "CAAPstINFRoot" feature. Here are the contents of the new Product document:
Fig. 1: Contents of the CAAPstINFDocument.CATProduct document.
![]() |
As you can see, the five "CAAPstINFPoint" features, the "CAAPstINFLine" feature and "CAAPstINFWire" feature are the elements in the list of components of the "CAAPstINFRoot1" feature. Also, notice that the "CAAPstINFLine1" feature points to "CAAPstINFPoint1" and "CAAPstINFPoint2" through a "SpecObject" link and that the "CAAPstINFWire1" feature points to "CAAPstINFPoint3", "CAAPstINFPoint4", and "CAAPstINFPoint5" through a "SpecObject" link as well.
You can see, in this case, that "CAAPstINFRoot1" aggregates the other features, meaning that if "CAAPstINFRoot1" were to be deleted, all of the aggregated features would be deleted as well. The "CAAPstINFLine" and the "CAAPstINFWire" objects, on the other hand, only reference the points that make up their definitions, meaning that if they were to be deleted, the points would continue to exist independently. Inversely, however, in the case of the line, for example, if ever one of the points were to be deleted, it would be necessary to delete the line as well, since its definition would no longer be valid.
[Top]
See the section entitled "How to Launch the CAAPstIntegrateNewFeatures Use Case" in the "Integrating New Features in a Product Structure" use case for a detailed description of how this use case should be launched.
The particular part of the use case described in this article is launched by executing the following command:
mkrun -c "CAAPstINFCreateDocument CatalogName DocumentStorageName"
where:
CatalogName
is the name and .CATfct
suffix of
the catalog containing the StartUps that are to be instantiated. This
catalog must be found in the current runtime view. You can reference here
the catalog called "CAAPstINFCatalog.CATfct" that is delivered along with
this use case, or you can reference the catalog you may have yourself
created using the CAAPstINFBuildCatalog.m module described by the
CAAPstINFBuildCatalog use case.DocumentStorageName
is the entire pathname, name and
.CATProduct suffix of the new document that is to be created. [Top]
The CAAPstINFCreateDocument use case is made of two modules, CAAPstINFCreateDocument.m and CAAPstINFModeler.m, both found in the CAAProductStructure.edu framework. CAAPstINFCreateDocument.m is a load module containing a single source program, CAAPstINFMainCreateDocument.cpp which creates the new document. This program also references the implementation classes of the CAAIPstINFRoot, CAAIPstINFPoint and CAAIPstINFLine interfaces called CAAEPstINFRoot, CAAEPstINFPoint, CAAEPstINFLine and CAAEPstINFWire whose source files are called CAAEPstINFRoot.cpp, CAAEPstINFPoint.cpp, CAAEPstINFLine.cpp and CAAEPstINFWire.cpp and whose header files are called CAAEPstINFRoot.h, CAAEPstINFPoint.h, CAAEPstINFLine.h and CAAEPstINFWire.h. These files can be found in the CAAPstINFModeler.m module.
Windows |
InstallRootDirectory\CAAProductStructure.edu\CAAPstINFCreateDocument.m
and CAAPstINFModeler |
Unix |
InstallRootDirectory/CAAProductStructure.edu/CAAPstINFCreateDocument.m
and CAAPstINFModeler |
where InstallRootDirectory
is the directory where the CAA CD-ROM
is installed.
[Top]
There are seven logical steps in CAAPstINFCreateDocument:
We will now comment each of these sections by looking at the code.
[Top]
Creating a New Product Document
... CATDocument *pDoc = NULL; rc = CATDocumentServices::New("Product", pDoc); ... |
A new Product document is created using the New
static method of CATDocumentServices and specifying a "Product" type of
document. This method returns a CATDocument pointer to the new document
that has been created.
[Top]
Creating a New Applicative Container
... CATIdent idAppliCont = "CAAPstINFCont"; CATUnicodeString appliContIdentifier = "PstINFContainer"; CATBaseUnknown *pINFAppliCont = NULL; rc = ::CATCreateApplicativeContainer(&pINFAppliCont, // appli cont created pDoc, // document idAppliCont, // type of appli cont IID_CATIContainer, // interface type of appli cont "CATFeatCont", // supertype of appli cont appliContIdentifier); // name of appli cont ... // Get a CATIContainer handle on the applicative container CATIContainer *piINFAppliCont = (CATIContainer*) pINFAppliCont; #ifdef INTERACTIVE_APPLICATION // Initialize the applicative container // For a product structure, the call to CATInit is only mandatory // in interactive CATInit * pInit = NULL ; rc = piINFAppliCont->QueryInterface(IID_CATInit, (void**) &pInit); ... pInit->Init(FALSE); .. // Declare the container to the Undo/redo mechanism // only in interactive otherwise the method returns E_FAIL // (as there is no undo/redo management in batch mode) rc = ::CATOmbPerformAfterContainerCreation(piINFAppliCont); ... #endif ... |
A new applicative container is created using the
CATCreateApplicativeContainer
global function. This function takes the
following arguments:
pINFAppliCont - this is the returned CATBaseUnknown pointer to the new applicative container that will be created.
pDoc - this is the CATDocument pointer to the current document in which the applicative container will be created.
idAppliCont - this is the late type of the new applicative container that will be created.
IID_CATIContainer - this is the requested interface that the returned CATBaseUnknown pointer to the new applicative container can be cast into.
"CATFeatCont" - this is the late type of the container this applicative container derives from; it must be "CATFeatCont" if the late type of the new applicative container itself (idAppliCont variable) is not "CATFeatCont" already.
appliContIdentifier - this is the identifier of the new applicative container.
Once the applicative container has been created, the CATBaseUnknown pointer to it can be directly cast to the requested interface, in this case, CATIContainer, which will be used to open the StartUp catalog.
For interactive applications, additional steps are required for the applicative container (see "Creating Features in an Applicative Container"):
Initialize the container with the Init method of the CATInit interface
Call the global function CATOmbPerformAfterContainerCreation after CATInit::Init to support the Undo/Redo mechanism
[Top]
... CATUnicodeString stgName = argv[1]; CATICatalog *piCatalog = NULL; CATUnicodeString clientId("CAAPstINFClientId"); rc = ::AccessCatalog (&stgName, &clientId, piINFAppliCont, &piCatalog); ... |
An existing StartUp catalog can be opened using the
AccessCatalog
global function. This function takes the following
arguments:
stgName - this is the name of the StartUp catalog that must be found in the runtime directory. In this use case, the name of the StartUp catalog is passed as an argument to the main program.
clientId - this is the client id assigned to the catalog at the time of its creation to protect it from unwanted access.
piINFAppliCont - this is a CATIContainer pointer to the applicative container in which the StartUps from this catalog will be instantiated.
piCatalog - this is the returned CATICatalog pointer to the opened StartUp catalog.
[Top]
Instantiating New Features in the Applicative Container
Instantiating a new feature in an applicative container is a two-step process: the StartUp must first be retrieved from the catalog and then it can be instantiated in the applicative container.
1. Retrieving a StartUp from the catalog.
... CATBaseUnknown *pRootSU = NULL; CATUnicodeString rootSUType("CAAPstINFRoot"); rc = piCatalog -> RetrieveSU(&pRootSU, &rootSUType, "CATISpecObject"); ... // Get a CATISpecObject handle on the CAAPstINFRoot StartUp CATISpecObject *piRootSU = (CATISpecObject*) pRootSU; ... |
In order to retrieve a StartUp from the catalog, use the
RetrieveSU
method of CATICatalog. This method takes the following
arguments:
pRootSU - this is the returned CATBaseUnknown pointer to the retrieved StartUp.
rootSUType - this is the late type of the StartUp that we want to retrieve.
"CATISpecObject" - this is the interface that will support this StartUp.
Once the StartUp has been retrieved, the CATBaseUnknown pointer can be directly cast to a pointer of the requested interface, in this case, CATISpecObject.
This example shows retrieving the "CAAPstINFRoot" StartUp. The retrieval of the "CAAPstINFPoint","CAAPstINFLine" and "CAAPstINFWire" StartUps is done in exactly the same way.
[Top]
2. Instantiating the StartUp in the applicative container.
... CATISpecObject *piRootInst1 = piRootSU -> Instanciate(CATUnicodeString("CAAPstINFRoot1"), pINFAppliCont); ... |
A new feature is created using the Instanciate
method of CATISpecObject. In this case, the CATISpecObject points
to the StartUp that was previously retrieved. This method takes the following
arguments:
"CAAPstINFRoot1" - this is the name of the new feature; its late type will always be the same as the StartUp.
pINFAppliCont - a pointer to the applicative container in which the new feature will be instantiated.
In this use case, two "CAAPstINFRoot" features are created,
"CAAPstINFRoot1" and "CAAPstINFRoot2". The first root feature will serve to
aggregate the five "CAAPstINFPoint" features, the "CAAPstINFLine" feature, and
the "CAAPstINFWire" feature which are all created here. The second root feature
is created in order to demonstrate certain CCP operations during the interactive
session. All of these features are instantiated in the same way and in the same
applicative container, using the Instanciate
method, as seen above.
[Top]
Valuating the New Feature's Attributes
1. Accessing "CAAPstINFPoint" attributes.
When creating new features, it is always a good idea to define specific interfaces for them in order to manipulate their data values in a proper way. The CAAIPstINFPoint interface is, therefore, defined to retrieve and set the "CAAPstINFPoint" attribute values.
1.1 Implementing the CAAIPstINFPoint interface.
The CAAIPstINFPoint interface is composed of six methods,
the first three to retrieve the values of the point coordinates: GetX
,
GetY
, and GetZ
; the other three to set the values of
the point coordinates: SetX
, SetY
and SetZ
.
The code example below is taken from the CAAEPstINFPoint implementation
class found in the CAAEPstINFPoint.cpp source file of the CAAPstINFModeler.m
module. Only the GetX
and the SetX
methods are shown,
the others being practically identical to these.
HRESULT CAAEPstINFPoint::GetX(double *pX) { CATISpecAttrAccess *piSpecAttrAccessOnPoint = NULL; HRESULT rc = QueryInterface (IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnPoint); ... CATISpecAttrKey *piXKey = piSpecAttrAccessOnPoint -> GetAttrKey ("X"); ... *pX = piSpecAttrAccessOnPoint -> GetDouble(piXKey); ... } |
The GetX
method returns a double
-type
pointer to the current "X" attribute value. To do this, first of all, it
retrieves a CATISpecAttrAccess interface pointer on the current
"CAAPstINFPoint" feature. Using this pointer, it executes the GetAttrKey
method for the attribute called "X" in order to retrieve a CATISpecAttrKey
pointer to the "X" attribute key. Then using this key as a parameter, it
executes the GetDouble
method of CATISpecAttrAccess in order
to retrieve the value of the x coordinate of the point, which it then returns
through a double
-type pointer.
HRESULT CAAEPstINFPoint::SetX(double iX) { CATISpecAttrAccess *piSpecAttrAccessOnPoint = NULL; HRESULT rc = QueryInterface (IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnPoint); ... CATISpecAttrKey *piXKey = piSpecAttrAccessOnPoint -> GetAttrKey ("X"); ... piSpecAttrAccessOnPoint -> SetDouble( piXKey, iX ); ... } |
The SetX
method does exactly the same thing as the
GetX
method, except that it executes the SetDouble
method of CATISpecAttrAccess, on the same attribute key as in GetX
,
in order to set a new value to the "X" attribute of the current "CAAPstINFPoint"
feature.
[Top]
1.2 Valuating "CAAPstINFPoint" attributes.
Valuating the "CAAPstINFPoint" features' attributes is done just after the instantiation of the features in the CAAPstINFMainCreateDocument.cpp file. This operation is simply performed by calling the "Set" methods defined in the CAAIPstINFPoint interface, whose implementation we just saw in the above section.
... CAAIPstINFPoint *piPstINFPoint = NULL; rc = piPointInst1 -> QueryInterface (IID_CAAIPstINFPoint, (void**) &piPstINFPoint); ... rc = piPstINFPoint -> SetX (0.0); ... rc = piPstINFPoint -> SetY (0.0); ... rc = piPstINFPoint -> SetZ (0.0); ... |
First of all, a CAAIPstINFPoint interface pointer is
retrieved for the first instance of "CAAPstINFPoint". Then, the methods for
valuating the point coordinates are called: SetX, SetY
and
SetZ
. Exactly the same procedure is employed for the following instances
of the "CAAPstINFPoint" feature.
[Top]
2. Accessing "CAAPstINFLine" attributes.
The CAAIPstINFLine interface is defined to retrieve and set the "CAAPstINFLine" attribute values.
2.1 Implementing the CAAIPstINFLine interface.
The CAAIPstINFLine interface is composed of two methods.
The first, GetPoint
, is used to retrieve the values of the first
and second attributes pointing to the "CAAPstINFPoint" features that define the
line. The second, SetPoint
, is used to set these same values. The
code example below is taken from the CAAEPstINFLine implementation class
found in the CAAEPstINFLine.cpp source file of the CAAPstINFModeler.m module.
HRESULT CAAEPstINFLine::GetPoint(int iNum, CATISpecObject **piPoint) { CATISpecAttrAccess *piSpecAttrAccessOnLine = NULL; HRESULT rc = QueryInterface (IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnLine); ... CATUnicodeString keyName; keyName = (1 == iNum ? "Point1" : "Point2"); CATISpecAttrKey *piPointKey = piSpecAttrAccessOnLine -> GetAttrKey (keyName); ... *piPoint = piSpecAttrAccessOnLine -> GetSpecObject(piPointKey); ... } |
The GetPoint
method returns a CATISpecObject
pointer to one of the "CAAPstINFPoint" features used to define the line,
depending on whether the first or the second point was requested in the
iNum
input parameter. To do this, first of all, it retrieves a
CATISpecAttrAccess interface pointer on the current "CAAPstINFLine" feature.
Using this pointer, it executes the GetAttrKey
method for the
attribute called either "Point1" or "Point2" in order to retrieve a
CATISpecAttrKey pointer to the attribute key. Then using this key as a
parameter, it executes the GetSpecObject
method of
CATISpecAttrAccess in order to retrieve a CATISpecObject pointer to
the "CAAPstINFPoint" feature defining the line and returns this value as an
output parameter.
HRESULT CAAEPstINFLine::SetPoint(int iNum, CATISpecObject *piPoint) { CATISpecAttrAccess *piSpecAttrAccessOnLine = NULL; HRESULT rc = QueryInterface (IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnLine); ... CATUnicodeString keyName; keyName = (1 == iNum ? "Point1" : "Point2"); CATISpecAttrKey *piPointKey = piSpecAttrAccessOnLine -> GetAttrKey (keyName); ... piSpecAttrAccessOnLine -> SetSpecObject(piPointKey, piPoint); ... } |
The SetPoint
method does exactly the same thing as
the GetPoint
method, except that it executes the
SetSpecObject
method of CATISpecAttrAccess on the same attribute
key, in order to set a new "CAAPstINFPoint" feature value to the attribute of
the current "CAAPstINFLine" feature.
[Top]
2.2 Valuating "CAAPstINFLine" attributes.
Now, once the "CAAPstINFPoint1" feature has been created, we want to valuate its attributes. Here is how this is done:
Valuating the "CAAPstINFLine" feature's attributes is done just
after the instantiation of the feature in the CAAPstINFMainCreateDocument.cpp
file. This operation is simply performed by calling the SetPoint
method defined in the CAAIPstINFLine interface, whose implementation we
just saw in the above section.
... CAAIPstINFLine *piPstINFLine = NULL; rc = piLineInst1 -> QueryInterface (IID_CAAIPstINFLine, (void**) &piPstINFLine); ... rc = piPstINFLine -> SetPoint (1, piPointInst1); ... rc = piPstINFLine -> SetPoint (2, piPointInst2); ... |
First of all, a CAAIPstINFLine interface pointer is
retrieved for the "CAAPstINFLine1" feature. Then, the SetPoint
method is called twice with the two instances of the "CAAPstINFPoint" feature
that define the line.
[Top]
3. Accessing "CAAPstINFWire" attributes.
The CAAIPstINFWire interface is defined to retrieve and set the "CAAPstINFWire" attribute values.
3.1 Implementing the CAAIPstINFWire interface.
The CAAIPstINFWire interface is composed of two methods.
The first, GetPoints
, is used to retrieve the list of
"CAAPstINFPoint" features that define the line. The second, SetPoints
,
is used to valuate this same list. The code example below is taken from the
CAAEPstINFWire implementation class found in the CAAEPstINFWire.cpp source
file of the CAAPstINFModeler.m module.
HRESULT CAAEPstINFWire::GetPoints(CATListPtrCATISpecObject **pPointList) { CATISpecAttrAccess *piSpecAttrAccessOnWire = NULL; HRESULT rc = QueryInterface (IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnWire); ... // Retrieve the key to the feature's "Points" attribute CATUnicodeString keyName = "Points"; CATISpecAttrKey *piPointKey = piSpecAttrAccessOnWire -> GetAttrKey (keyName); ... // Scan through the list of features referenced by the attribute, // retrieve each feature and append it to the list to be returned to the caller. *pPointList = new CATListPtrCATISpecObject(); CATISpecObject *piPoint = NULL; piSpecAttrAccessOnWire -> Beginning(piPointKey); while (piSpecAttrAccessOnWire -> Next(piPointKey)) { piPoint = piSpecAttrAccessOnWire -> GetSpecObject(piPointKey); (*pPointList) -> Append(piPoint); piPoint = NULL; } ... } |
The GetPoint
method returns a
CATListPtrCATISpecObject pointer to the list containing the "CAAPstINFPoint"
features used to define the wire. To do this, first of all, it retrieves a
CATISpecAttrAccess interface pointer on the current "CAAPstINFWire" feature.
Using this pointer, it executes the GetAttrKey
method for the
attribute called "Points" in order to retrieve a CATISpecAttrKey pointer
to the attribute key. Then using this key as a parameter, it loops through the
list of features using the Beginning
and Next
methods
of CATISpecAttrAccess and executes the GetSpecObject
method
in order to retrieve each CATISpecObject pointer to the "CAAPstINFPoint"
feature defining the line, which it appends to the list to be returned as an
output parameter.
HRESULT CAAEPstINFWire::SetPoints(CATListPtrCATISpecObject *pPointList) { CATISpecAttrAccess *piSpecAttrAccessOnWire = NULL; HRESULT rc = QueryInterface (IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnWire); ... // Retrieve the key to the feature's "Points" attribute CATUnicodeString keyName = "Points"; CATISpecAttrKey *piPointKey = piSpecAttrAccessOnWire -> GetAttrKey (keyName); ... // If the list of attributes is already valuated, initialize it to NULL in order // to entirely re-create it. int nb = piSpecAttrAccessOnWire -> GetListSize(piPointKey); if ( 0 != nb ) { piSpecAttrAccessOnWire -> UnsetAttributeValue(piPointKey); } // Scan through the list of features passed in the argument, // retrieve each feature from the list and save it in the list of features // referenced by the "Points" attribute. CATISpecObject *piPoint = NULL; for (int i=1; i<=pPointList->Size(); i++) { piPoint = (*pPointList)[i] ; piSpecAttrAccessOnWire -> SetSpecObject(piPointKey, piPoint, 0); piPoint = NULL; } ... } |
The SetPoints
method does exactly the same thing as
the GetPoints
method, except that it executes the
SetSpecObject
method of CATISpecAttrAccess on the same attribute
key, in order to add the given number of "CAAPstINFPoint" features to the list
attribute of the current "CAAPstINFWire" feature. Note that the list is entirely
re-created every time the method is called. This is done by using the
UnsetAttributeValue
method of CATISpecAttrAccess in order to
re-initialize the list of SpecObjects.
[Top]
3.2 Valuating "CAAPstINFWire" attributes.
Valuating the "CAAPstINFWire" feature's attributes is done just
after the instantiation of the feature in the CAAPstINFMainCreateDocument.cpp
file. This operation is simply performed by calling the SetPoints
method defined in the CAAIPstINFWire interface, whose implementation we
just saw in the above section.
... CAAIPstINFWire *piPstINFWire = NULL; rc = piWireInst1 -> QueryInterface (IID_CAAIPstINFWire, (void**) &piPstINFWire); ... CATListPtrCATISpecObject pointList; pointList.Append (piPointInst3); pointList.Append (piPointInst4); pointList.Append (piPointInst5); cout << "Size of pointlist = " << pointList.Size() << endl; rc = piPstINFWire -> SetPoints (&pointList); ... |
First of all, a CAAIPstINFWire interface pointer is
retrieved for the "CAAPstINFWire1" feature. Then, the SetPoints
method is called with the list of the "CAAPstINFPoint" features that
define the wire.
[Top]
Aggregating the New Features to the Root Feature Node
1. Implementing the CAAIPstINFRoot interface.
The CAAIPstINFRoot interface is composed of two methods.
The first, AddChild
, is used to aggregate a new feature to the
"CAAPstINFRoot" feature representing a root node in the product structure. The
second, GetChildren
, retrieves the list of features aggregated by
the "CAAPstINFRoot" feature. The code example below is taken from the
CAAEPstINFRoot implementation class found in the CAAEPstINFRoot.cpp source
file of the CAAPstINFModeler.m module.
1.1 AddChild.
This method has three distinct parts. The first part deals with the data modifications that are necessary whenever a new feature is created and aggregated to the "CAAPstINFRoot" node. The second part deals with the update of the specs tree to display the new feature. And finally, the third part deals with the necessary notification of the creation that needs to be sent so that the new feature can be visualized.
1.1.1 AddChild: Data modification.
... HRESULT CAAEPstINFRoot::AddChild (CATISpecObject *piFeature) { HRESULT rc; CATISpecAttrAccess *piAttrAccess = NULL; rc = this -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piAttrAccess); ... // Retrieve the attribute key in order to access the list of aggregated features CATISpecAttrKey *piListKey = piAttrAccess -> GetAttrKey("ListOfComponents"); ... // Add the new feature to the end of the list piAttrAccess -> SetSpecObject (piListKey, piFeature); ... |
Using a CATISpecAttrAccess pointer retrieved on the
current root feature, we execute the GetAttrKey
method in order to
retrieve a CATISpecKey pointer to the "ListOfComponents" attribute
defined for the "CAAPstINFRoot" feature. Then, using this key, we execute the
SetSpecObject
method of CATISpecAttrAccess, specifying the
new feature that is to be aggregated (or, in other words, added to the list as a
component feature).
[Top]
1.1.2 AddChild: Refresh of the specs tree.
... // Refresh the navigation tree CATIRedrawEvent *piRedrawOnRoot = NULL; rc = QueryInterface(IID_CATIRedrawEvent, (void**) &piRedrawOnRoot); ... piRedrawOnRoot -> Redraw(); ... |
Once the data modifications are complete, in order to update the
specs tree, we retrieve a CATIRedrawEvent pointer on the current
"CAAPstINFRoot" feature and execute the Redraw
method.
[Top]
1.1.3 AddChild: Refresh of the visualization.
... // Force the visualization of the new feature by sending an event on the Product root // Retrieve a pointer to the current document CATILinkableObject *piLinkableOnRoot = NULL; rc = QueryInterface(IID_CATILinkableObject, (void**) &piLinkableOnRoot); ... CATDocument *pDoc = piLinkableOnRoot -> GetDocument(); ... // Retrieve the document's product root CATIDocRoots* piDocRootsOnDoc = NULL; rc = pDoc -> QueryInterface(IID_CATIDocRoots, (void**) &piDocRootsOnDoc); ... // The document's root product is the first element of the list returned by GiveDocRoots CATListValCATBaseUnknown_var *pProductList = piDocRootsOnDoc -> GiveDocRoots(); CATBaseUnknown *pRootProduct = NULL; CATIProduct *piRootProduct = NULL; ... if (pProductList->Size()) { pRootProduct = (*pProductList)[1]; ... rc = pRootProduct -> QueryInterface(IID_CATIProduct, (void**) &piRootProduct); ... } ... // Retrieve a CATIModelEvents pointer on the product root and connect the feature CATIModelEvents *piModelEventsOnProductRoot = NULL; rc = piRootProduct -> QueryInterface(IID_CATIModelEvents, (void**) &piModelEventsOnProductRoot); ... piModelEventsOnProductRoot -> ConnectTo(piFeature); // Send a notification of the creation to the view CATCreate ntfCreate(piFeature, piModelEventsOnProductRoot); piModelEventsOnProductRoot -> Dispatch(ntfCreate); piModelEventsOnProductRoot -> Release(); piModelEventsOnProductRoot = NULL; ... } |
The visualization process must be notified of the creation through an event notification that must be sent at the Product level. This is because the real visualization root of our features is the Product root. The "CAAPstINFRoot" nodes serve only to better structure our features; they do not enter into the visualization process.
Therefore, the first step in sending a creation notification is
to retrieve the Product root. To do this, it is necessary to retrieve a
CATDocument pointer to the current document using the GetDocument
method of CATILinkableObject on the current aggregating "CAAPstINFRoot"
feature. Then, from the CATDocument pointer, we can retrieve a
CATIDocRoots interface pointer and execute the GiveDocRoots
method. This method returns a list of the documents' products, the first of
which is the Product root. Now, on the Product root, we can retrieve a
CATIModelEvents interface pointer and execute the ConnectTo
method for the new feature that has been created. Then, a new CATCreate
object is instantiated for the new feature on the Product root and this
CATCreate
object is then dispatched through the Dispatch
method of CATIModelEvents.
[Top]
1.2 GetChildren.
HRESULT CAAEPstINFRoot::GetChildren (CATListValCATBaseUnknown_var **pList) { CATISpecAttrAccess *piAttrAccessOnRoot = NULL; HRESULT rc = this -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piAttrAccessOnRoot); ... CATISpecAttrKey *piListComponentKey = NULL; piListComponentKey = piAttrAccessOnRoot -> GetAttrKey ("ListOfComponents"); ... CATISpecObject *piComponent = NULL; piAttrAccessOnRoot -> Beginning(piListComponentKey); while (piAttrAccessOnRoot -> Next(piListComponentKey)) { piComponent = piAttrAccessOnRoot -> GetSpecObject(piListComponentKey); ... (*pList) -> Append(piComponent); ... } ... } |
This method retrieves a list of the features aggregated by this
"CAAPstINFRoot" node. To do this, it first retrieves a CATISpecAttrAccess
interface pointer on the current "CAAPstINFRoot". Then, using the
GetAttrKey
method, it retrieves the CATISpecAttrKey corresponding
to the "ListOfComponents" attribute. Using this key, it then loops through the
list of components using the Beginning
and Next
methods of CATISpecAttrAccess and executes the GetSpecObject
on each list element in order to retrieve the CATISpecObject pointer
corresponding to the aggregated feature. It appends this object to the list that
is to be returned using the Append
method of the
CATListVarCATBaseUnknown collection.
2. Valuating "CAAPstINFRoot" attributes.
Valuating the "CAAPstINFRoot" feature's attributes is done in
the CAAPstINFMainCreateDocument.cpp file, after the instantiation of all of the
features that are to be aggregated to it. This operation is simply performed by
calling the AddChild
method defined in the CAAIPstINFRoot
interface, whose implementation we just saw in the above section.
... CAAIPstINFRoot *piPstINFRoot = NULL; rc = piRootInst1 -> QueryInterface (IID_CAAIPstINFRoot, (void**) &piPstINFRoot); ... rc = piPstINFRoot -> AddChild(piPointInst1); ... rc = piPstINFRoot -> AddChild(piPointInst2); ... rc = piPstINFRoot -> AddChild(piPointInst3); ... rc = piPstINFRoot -> AddChild(piPointInst4); ... rc = piPstINFRoot -> AddChild(piPointInst5); ... rc = piPstINFRoot -> AddChild(piLineInst1); ... rc = piPstINFRoot -> AddChild(piWireInst1); ... |
Use the CAAIPstINFRoot::AddChild
method to
aggregate a new feature to a "CAAPstINFRoot". This method performs the necessary
data modifications to aggregate the new feature to the "CAAPstINFRoot", performs
a refresh of the navigation tree in order for the new feature to be taken into
account and finally, sends a creation notification event to the product root in
order for the new feature to be visualized.
[Top]
Saving the New Product Document
... rc = CATDocumentServices::SaveAs (*pDoc, argv[2]); ... |
Use the SaveAs
static method of
CATDocumentServices to save the new document. The storage pathname of the
new document is passed as an argument to the use case.
[Top]
The CAAPstINFCreateDocument use case has shown you how to create new features "from scratch" in an applicative container of a Product document.
[Top]
Version: 1.2 [Aug 2004] | Document revised |
Version: 2 [May 2003] | Add reference to "Creating Features in an Applicative Container" |
Version: 1 [May 2002] | Document created |
[Top] |
Copyright © 2002, Dassault Systèmes. All rights reserved.