PPR Hub |
Product Modeler |
Initializing the Applicative Container at RuntimePerforming runtime initialization tasks |
Use Case | ||
CAAPstIntegrateNewFeatures > CAAPstINFBuildCatalog > CAAPstINFCreateDocument > CAAPstINFInitCont > CAAPstINFNavigate > CAAPstINFVisu > CAAPstINFGraphicalProperties > CAAPstINFEdit > CAAPstINFCCP > CAAPstINFDelete > CAAPstINFUpdate |
AbstractThis article discusses the CAAPstINFInitCont use case. This use case explains what necessary initialization tasks must be performed in order for the provider and visualization mechanisms to be correctly declared to the document during the loading process. |
This use case is intended to illustrate how to program the necessary initialization tasks that must be performed in order for certain feature behaviors to function correctly at runtime. One of these initialization tasks concerns the declaration of providers. Because the features created in this use case are "from scratch" features, meaning that they do not derive from any existing feature that may already be known to the navigation, visualization or update processes, it is necessary to use providers in order to be able to take them into account. The declaration of providers is not persistent to the document. It is necessary, therefore, to declare them each time the document is opened. Since providers refer to "from scratch" features that are stored in applicative containers, it seems reasonable, then, to perform the declaration of providers in the initialization process of the applicative container, which is called whenever the Product document is loaded into the session. Likewise, visualization connections between objects is also a non-persistent mechanism that has to be renewed at document load-time. Therefore, in this use case, you will see how to program the provider declarations that handle the integration of your new features in the navigation, visualization and update processes as well as how to connect the root features to the Product root and the aggregated features to their feature root in order to correctly structure the document for visualization purposes.
You should already be familiar with the CAAPstIntegrateNewFeatures use case article [1] in order to more easily understand the context of this particular 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]. You may also want to look at the "Using the Provider Mechanism" use case [3] which describes the basics of the Provider mechanism. Finally, it may be useful for you to look over the "Product Structure Model" technical article [4] as well.
[Top]
The CAAPstINFInitCont a use case that is part of the CAAPstIntegrateNewFeatures use case defined in the CAAProductStructure.edu framework that illustrates the integration of ObjectSpecsModeler, ObjectModelerBase and ProductStructure framework capabilities in the scope of a Product document.
[Top]
This use case essentially describes the applicative container's implementation of the CATInit interface in which the necessary provider declarations and feature inter-connections are performed.
Let's take a look at the contents of the Product document. 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. A "CAAPstINFLine" feature is instantiated next, whose attribute values reference the first two "CAAPstINFPoint" features. Finally, a "CAAPstINFWire" feature is instantiated, whose attribute value references a list containing 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 "CAAPstINFPoint", "CAAPstINFLine" and "CAAPstINFWire" types of features are the elements in the list of components of the "CAAPstINFRoot1" feature. Also, notice that the "CAAPstINFLine1" attributes point to "CAAPstINFPoint1" and "CAAPstINFPoint2" through a "SpecObject" link and that the "CAAPstINFWire1" attribute points to a list containing the "CAAPstINFPoint3", "CAAPstINFPoint4", "CAAPstINFPoint5" features also through a "SpecObject" link.
You can see, in this case, that the "CAAPstINFRoot1" feature aggregates the other features, meaning that if "CAAPstINFRoot1" were to be deleted, all of the aggregated features would be deleted as well. The "CAAPstINFLine" object, on the other hand, only references the two points that make up its definition, meaning that if it is deleted, the two points continue to exist independently. Inversely, however, if ever one of the two points is deleted, it is necessary to delete the line as well, since its definition will no longer be valid.
Note that nowhere in this document have we specified where the
"CAAPstINFRoot" nodes themselves are to be structured. This operation
will take place during the initialization of the applicative container, at
runtime. When the Product document is opened in the CATIA interactive session,
the implementation of the CATInit::Init
method for the
"CAAPstINFCont" applicative container is executed. This method
declares the provider implementations that will need to be executed during the
navigation and visualization processes in order to structure the
"CAAPstINFRoot" features under the Product root in the specs tree and
to be able to visualize the geometry of the point and line features. So, when
the document is finally visualized, it looks like this:
![]() |
As you can see, the "CAAPstINFRoot1" and "CAAPstINFRoot2" features are structured directly under the Product root. This is defined in the navigation provider implementation. Remember that the navigation provider mechanism has been implemented for all products in a Product document. This means that during the navigation process, for each product node, any navigation provider that is currently declared to the document will be executed. So, in order to structure the "CAAPstINFRoot" features under the product root, the navigation provider code retrieves the "CAAPstINFRoot" types of features from the "CAAPstINFCont" applicative container and returns them as children nodes whenever the provider is called by the Product root object during the navigation process.
Note also that the geometry of the points, line and wire is also visualized, whereas these are applicative features stored in an applicative container and are not automatically taken into account during the visualization process. In order these objects to be treated, a visualization provider must also have been declared, which, when called, returns the list of the aggregating feature root nodes. Then, the CATI3DGeoVisu implementation for each feature root as well as for each aggreagted object in order to define the visualization.
Remember that "CAAPstINFLine1" is defined based on "CAAPstINFPoint1" and "CAAPstINFPoint2". If ever one of these point features were to be modified, the line feature would have to be updated. But, because any number of features could be dependent on the same point feature for their own definition, the update process is implemented at the Product root level. The Product root, however, does not have any knowledge of all of the different "from scratch" features that may exist in the document. It is necessary, therefore, to declare an update provider that will be called by the Product root whenever it is requested to update.
The scope of this use case, however, is not to illustrate the provider mechanism for these processes, but rather to demonstrate the construction of the document and the declaration of the necessary providers. Other use cases dealing with navigation [5], visualization [6] and update [7] will detail each of these processes.
[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.
Specifically, the code described in this article is executed upon loading the Product document (you can use the CAAPstINFDocument.CATProduct document that can be found in the CNext/resources/graphic directory of the CAAProductStructure.edu framework) into the CATIA session. It is during the loading process that the initialization of any applicative containers occurs.
[Top]
This use case describes the implementation class of the CATInit interface, called CAAEPstINFInitCont, which is found in the CAAEPstINFInitCont.cpp source file and CAAEPstINFInitCont.h header file of the CAAPstINFModeler.m shared library.
Windows | InstallRootDirectory\CAAProductStructure.edu\CAAPstINFModeler.m |
Unix | InstallRootDirectory/CAAProductStructure.edu/CAAPstINFModeler.m |
where InstallRootDirectory
is the directory where the CAA CD-ROM
is installed.
[Top]
There are three logical steps in CAAPstINFInitCont:
We will now comment each of these sections by looking at the code.
[Top]
Declaring Available Providers to the Document
The necessary declarations related to the applicative container
that must be performed at runtime can be made in the implementation of the Init
method of CATInit. This method is executed at the time the document is
loaded into the interactive session. It essentially contains the declarations of
the provider implementations that have been supplied in order to integrate new
features in various CATIA mechanisms. In this use case, we illustrate the
navigation, visualization and update providers. Following is the code of the
implementation class called CAAEPstINFInitCont of the CATInit
interface for the "CAAPstINFCont" applicative container defined in
this use case. The code of this implementation can be found in the
CAAEPstINFInitCont.cpp source file of the CAAPstINFModeler.m module.
void CAAEPstINFInitCont::Init (CATBoolean destroyExistingData) { cout << "***** CAAPstINFCont: CAAEPstINFInitCont::Init" << endl; // Retrieve the current document CATILinkableObject *piLinkableOnCont = NULL; HRESULT rc = this -> QueryInterface(IID_CATILinkableObject, (void**) &piLinkableOnCont); if (!SUCCEEDED(rc)) return; CATDocument *pDoc = piLinkableOnCont -> GetDocument(); piLinkableOnCont -> Release(); piLinkableOnCont = NULL; if (NULL == pDoc) return; cout << "Document retrieved OK" << endl << flush; // Retrieve a CATIProviders pointer on the current document CATIProviders *piProvidersOnDocument = NULL; rc = pDoc -> QueryInterface(IID_CATIProviders, (void**) &piProvidersOnDocument); if (!SUCCEEDED(rc)) return; // Declare the navigation provider to list the feature root(s) CAAPstINFNavigProviderRoot *pNavigProviderRoot = new CAAPstINFNavigProviderRoot(); rc = piProvidersOnDocument -> AddProvider (CATINavigateProvider::ClassId(), pNavigProviderRoot); pNavigProviderRoot -> Release(); pNavigProviderRoot = NULL; if (!SUCCEEDED(rc)) return; else cout << "Navigation provider for root declared OK" << endl << flush; // Declare the visualization provider to list the children of the applicative container CAAPstINFVisuProviderRoot *pVisuProviderRoot = new CAAPstINFVisuProviderRoot(); rc = piProvidersOnDocument -> AddProvider (CATI3DVisuProvider::ClassId(), pVisuProviderRoot); pVisuProviderRoot -> Release(); pVisuProviderRoot = NULL; if (!SUCCEEDED(rc)) return; else cout << "Visualization provider declared OK" << endl << flush; // Declare the line and wire feature update provider to re-build line and wire after modification // of points CAAPstINFUpdateProviderLine *pUpdateProviderLine = new CAAPstINFUpdateProviderLine(); rc = piProvidersOnDocument -> AddProvider (CATIUpdateProvider::ClassId(), pUpdateProviderLine); pUpdateProviderLine -> Release(); pUpdateProviderLine = NULL; piProvidersOnDocument -> Release(); piProvidersOnDocument = NULL; if (!SUCCEEDED(rc)) return; else cout << "Line and wire update provider declared OK" << endl << flush; ... |
Essentially, this method performs the provider declarations for
navigation, visualization and update. Remember that providers are declared to
the document. Therefore, it is first necessary to retrieve a CATDocument
pointer to the current document. This is done through the CATILinkableObject::GetDocument
method. Then, a CATIProviders interface pointer can be retrieved on the
document. Using this interface, we can execute the AddProvider
method for each provider implementation. This method takes the following
arguments:
Provider interface name: this is the CLSID of the provider interface.
Provider implementation object: this is a pointer to the provider implementation corresponding to the interface declared in the first argument.
[Top]
Connecting Features to their Visualization Roots
In this section you will see how each feature root is connected to the Product root and each aggregated feature is connected to its feature root. This connecting operation is necessary in order for the visualization process to work correctly.
1. Retrieve the Product root.
// Retrieve the Product root CATIProduct *piRootProduct = NULL; CATIDocRoots* piDocRootsOnDoc = NULL; rc = pDoc -> QueryInterface(IID_CATIDocRoots, (void**) &piDocRootsOnDoc); if (SUCCEEDED(rc)) { // Retrieve the root product which is the first element of root elements CATListValCATBaseUnknown_var* pRootProducts = piDocRootsOnDoc -> GiveDocRoots(); piDocRootsOnDoc -> Release(); piDocRootsOnDoc = NULL; CATBaseUnknown *pBaseRootProduct = NULL; if (pRootProducts && pRootProducts->Size()) { pBaseRootProduct = (*pRootProducts)[1]; delete pRootProducts; pRootProducts = NULL; rc = pBaseRootProduct -> QueryInterface(IID_CATIProduct, (void**) &piRootProduct); if (FAILED(rc)) return; } } else return; ... |
It is necessary to first retrieve the Product document's root because all the
feature roots will be connected to it. In order to retrieve the product roots,
we first need to retrieve a CATIDocRoots pointer on the current document.
Then, using the GiveDocRoots
method, we retrieve a list of
products, the first of which is the Product document's root. We then save this
object in a CATIProduct pointer.
[Top]
2. Connect the features to their roots.
2.1 Retrieve a list of the applicative container's features.
... CATUnicodeString appliContIdentifier("PstINFContainer"); CATBaseUnknown *pApplicativeContainer = NULL; rc = ::CATGetApplicativeContainer (&pApplicativeContainer, pDoc, IID_CATIClientContainer, appliContIdentifier); if (SUCCEEDED(rc)) cout << "Applicative container retrieved OK" << endl << flush; else { cout << "ERROR in retrieving applicative container" << endl << flush; return; } // Retrieve a pointer to CATIClientContainer in order to list the members // of the applicative container. CATIClientContainer *piClientOnAppliCont = (CATIClientContainer *) pApplicativeContainer; // Retrieve the list of features in the applicative container CATUnicodeString clientId("CAAPstINFClientId"); CATListPtrCATBaseUnknown *pMemberList = new CATListPtrCATBaseUnknown(); rc = piClientOnAppliCont -> ListMembers(IID_CATISpecObject, clientId, &pMemberList); pApplicativeContainer -> Release(); pApplicativeContainer = NULL; if (SUCCEEDED(rc)) cout << "Member list retrieved OK" << endl << flush; else { cout << "ERROR in retrieving member list" << endl << flush; return; } cout << "Number of members in applicative container: " << pMemberList->Size() << endl << flush; // Retrieve a CATIModelEvents pointer to the Product root CATIModelEvents *piModelEventsOnProductRoot = NULL; rc = piRootProduct -> QueryInterface(IID_CATIModelEvents, (void**) &piModelEventsOnProductRoot); if (FAILED(rc)) return; piRootProduct -> Release(); piRootProduct = NULL; ... |
In order to retrieve the contents of the applicative container, we first need
to get a pointer to the applicative container itself, which can be done using
the CATGetApplicativeContainer
global function. Then, since the CATIClientContainer
interface was requested in this call, we can simply cast the returned CATBaseUnknown
pointer to CATIClientContainer in order to access the ListMembers
method. This method returns a list of all of the features contained in the
applicative container. Once we have retrieved all of our features, we can
prepare to connect them first of all to the Product root by retrieving a CATIModelEvents
pointer on the Product root itself.
[Top]
2.2 Connect the feature roots to the Product root.
... CATUnicodeString rootType(""); CATISpecObject *piSpecMember = NULL; for(int i=1;i<=pMemberList->Size();i++) { piSpecMember = (CATISpecObject *) (*pMemberList)[i]; rootType = piSpecMember -> GetType(); if (rootType == "CAAPstINFRoot") { // Connect the feature root to the Product root piModelEventsOnProductRoot -> ConnectTo((*pMemberList)[i]); ... |
The list is scanned for "CAAPstINFRoot" feature types.
When one is found, it is connected to the Product root using the ConnectTo
method of CATIModelEvents.
[Top]
2.3 Connect every aggregated feature to its root.
... // Retrieve the list of aggregated or referenced features CATISpecAttrAccess *piSpecAttrAccessOnFeatureRoot = NULL; rc = (*pMemberList)[i] -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnFeatureRoot); if (FAILED(rc)) return; CATUnicodeString keyName = "ListOfComponents"; CATISpecAttrKey *piComponentKey = piSpecAttrAccessOnFeatureRoot -> GetAttrKey (keyName); if (NULL == piComponentKey) return; CATIModelEvents *piModelEventsOnFeatureRoot = NULL; rc = (*pMemberList)[i] -> QueryInterface(IID_CATIModelEvents, (void**) &piModelEventsOnFeatureRoot); if (FAILED(rc)) return; CATISpecObject *piFeatureComponent = NULL; piSpecAttrAccessOnFeatureRoot -> Beginning(piComponentKey); while (piSpecAttrAccessOnFeatureRoot -> Next(piComponentKey)) { // Connect each feature to its root piFeatureComponent = piSpecAttrAccessOnFeatureRoot -> GetSpecObject(piComponentKey); piModelEventsOnFeatureRoot -> ConnectTo((CATBaseUnknown *)piFeatureComponent); piFeatureComponent = NULL; } piSpecAttrAccessOnFeatureRoot -> Release(); piSpecAttrAccessOnFeatureRoot = NULL; piComponentKey -> Release(); piComponentKey = NULL; piModelEventsOnFeatureRoot -> Release(); piModelEventsOnFeatureRoot = NULL; } (*pMemberList)[i] -> Release(); (*pMemberList)[i] = NULL; piSpecMember = NULL; } piModelEventsOnProductRoot -> Release(); piModelEventsOnProductRoot = NULL; delete pMemberList; pMemberList = NULL; ... |
For each feature root, we would now like to retrieve every
feature it aggregates and connect this feature to it. In order to do this, we
first need to get a CATISpecAttrAccess pointer on the feature root. Then,
using the GetAttrKey
method, we can retrieve the attribute key
pointing to the list of features. Next, we prepare to connect the aggregated
features by retrieving a CATIModelEvents pointer on the feature root.
Note that an implementation of this interface for the feature root must already
have been provided. Now we can scan through the list of features using the Beginning
and Next
methods of CATISpecAttrAccess and retrieve a
pointer to each feature using the GetSpecObject
method. Finally,
each aggregated feature can be connected to its root using the ConnectTo
method of CATIModelEvents.
[Top]
... // Declare the CCP Format ::SpecBindNativeFormat("CAAPstINFCont"); ... |
In order for the Cut/Copy/Paste mechanism to function correctly
on the applicative container, it is necessary to declare it as the CCP format
using the SpecBindNativeFormat
global function.
[Top]
The CAAPstINFInitCont use case has shown you how to initialize the applicative container at runtime so that navigation, visualization and update processes can account for these new features through provider declarations and visualization connections.
[Top]
[1] | Integrating New Features in a Product Document |
[2] | Feature Modeler Overview |
[3] | Using the Provider Mechanism |
[4] | The Product Structure Model |
[5] | Enabling the Navigation of New Features in a Product Document |
[6] | Enabling the Visualization of New Features in a Product Document |
[7] | Enabling New Features in a Product Document to be Updated |
[Top] |
Version: 1 [June 2002] | Document created |
[Top] |
Copyright © 2002, Dassault Systèmes. All rights reserved.