PPR Hub |
Product Modeler |
Enabling the Navigation of New Features in a Product DocumentIntegrating new features in the specs tree |
Use Case | ||
CAAPstIntegrateNewFeatures > CAAPstINFBuildCatalog > CAAPstINFCreateDocument > CAAPstINFInitCont > CAAPstINFNavigate > CAAPstINFVisu > CAAPstINFGraphicalProperties > CAAPstINFEdit > CAAPstINFCCP > CAAPstINFDelete > CAAPstINFUpdate |
AbstractThis article discusses the CAAPstINFNavigate use case. This use case explains how to integrate new features created "from scratch" in the product structure's specs tree. |
This use case is intended to illustrate how new features created "from scratch" in an applicative container of a Product document can be integrated in the specs tree of the product structure. The specs tree is created through CATIA's navigation process. This is a mechanism that allows a feature to be visualized as the node of a tree and enables it to display its children as nodes as well. The native CATIA navigation process for each document type takes into account the different containers and features that are native to that particular document. However, it has no knowledge of features created in user-defined applicative containers. The purpose of this use case is to show how these types of features can nevertheless be displayed in the product structure specs tree under a product node in a Product document.
For a better understanding of the navigation process, it may be helpful for you to look at the ObjectModelerBase use case article entitled "The Object Navigator" [1].
[Top]
The CAAPstINFNavigate is a use case that is part of the CAAPstIntegrateNewFeatures use case defined in the CAAProductStructure.edu framework that illustrates the integration of ObjectModelerBase, ObjectSpecsModeler and ProductStructure framework capabilities in the scope of a Product document.
[Top]
This use case illustrates the integration in the navigation process of new features created in an applicative container within a Product document. Following are the contents of the applicative container we will be working with in the CAAPstINFDocument.CATProduct document supplied with this use case.
Fig. 1: Contents of the CAAPstINFCont applicative container.![]() |
As you can see, initially, we are basically working with eight features: two "CAAPstINFRoot" features, five "CAAPstINFPoint" features, one "CAAPstINFLine" feature and one "CAAPstINFWire" feature. None of these objects would natively appear in the product structure specs tree. Looking at this data, we can see that there would be two ways to add them to the specs tree:
Given the way our data has been designed, the second choice seems to be the natural one: we have two root nodes, one of which aggregates five points, a line and a wire, the other being empty. The resulting product structure we would like to arrive at would look like this:
ProductRoot | |____ CAAPstINFRoot1 | | | |____ CAAPstINFPoint1 | CAAPstINFPoint2 | CAAPstINFPoint3 | CAAPstINFPoint4 | CAAPstINFPoint5 | CAAPstINFLine1 | CAAPstINFWire1 | |____ CAAPstINFRoot2
So, basically, since the Product nodes are all natively taken into account by the navigation process, we would like to insert the "CAAPstINFRoot" features somehow under one of them, the Product root itself, for example. The solution to this is to use a navigation provider supplied by the ProductStructure framework. The interface corresponding to this provider is called CATINavigateProvider and corresponds to the CATINavigateObject interface. The native navigation process works by requesting each node it meets to list its children. Thus, the first node in the product structure, the Product root, would list all of the products it aggregates. Each product in turn would list its aggregated objects. When a navigation provider is active, it is called at each step as well. It is up to the navigation provider algorithm to decide to which caller it wants to return the list of its children.
In our example, the navigation provider algorithm returns the two "CAAPstINFRoot" features if it is called by the Product root. The navigation process then aggregates these features as nodes under the Product root. Once they are in the navigation process, the native CATINavigateObject interface implementation for the "CAAPstINFRoot" feature is called to request the list of its children.
This use case will explain how to program the navigation provider (CATINavigateProvider implementation) and the native navigation implementation (CATINavigateObject implementation) so that the features created in an applicative container can be correctly structured in the specs tree.
Here is an image of a CATIA session where the CAAPstINFDocument.CATProduct has been loaded. Notice that the navigation process has taken our initial scheme into account and has structured the new geometric features under "CAAPstINFRoot1" and both "CAAPstINFRoot" features under the Product root.
Fig. 2: Initial loading of CAAPstINFDocument.CATProduct document.![]() |
What is very important to remember is that provider implementations are
runtime mechanisms. In order to activate them at runtime, it is necessary to
declare them to the document during its initiation. Because our features are all
created in the same applicative container, a natural place for declaring our
providers would be during the initialization of the applicative container. This
means implementing the CATInit::Init
method for our
applicative container. This code is described in the "Initializing the
Applicative Container at Runtime" article [2] related to this use case.
[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 CATINavigateObject and CATINavigateProvider implementations are executed in order for the specs tree to be correctly initialized and to become navigatable.
[Top]
This use case describes the implementation class of the CATINavigateProvider interface, called CAAEPstINFNavigProviderRoot, which is found in the CAAEPstINFNavigProviderRoot.cpp source file and CAAEPstINFNavigProviderRoot.h header file. It also describes the implementation class of the CATINavigateObject interface, called CAAEPstINFNavigateObjectRoot, which is found in the CAAEPstINFNavigateObjectRoot.cpp source file and CAAEPstINFNavigateObjectRoot.h header file. Both implementations are found in 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 two logical steps to CAAPstINFNavigate:
We will now comment each of these sections by looking at the code.
[Top]
Coding a Navigation Provider Implementation of CATINavigateProvider
The purpose of this navigation provider implementation is to return the list
of "CAAPstINFRoot" features found in the "CAAPstINFCont"
applicative container if called by the Product root in order to structure these
features under the Product root in the specs tree. The navigation provider is a
simple implementation (in other words, it is not an extension of an existing
component) that implements the CATINavigateProvider interface. It
contains only one method, GetChildren
, which is described in detail
below.
1. Verify that the caller object is the Product root.
HRESULT CAAPstINFNavigProviderRoot::GetChildren(CATBaseUnknown *pObj, CATLISTP(CATBaseUnknown) **pListChildren) { cout << "***** CAAPstINFNavigProviderRoot::GetChildren" << endl << flush; // Retrieve a CATIProduct handle on the caller object CATIProduct *piProductOnObj = NULL; HRESULT rc = pObj -> QueryInterface (IID_CATIProduct, (void**) &piProductOnObj); if (SUCCEEDED(rc)) { // Retrieve the father of the product: if it has none, this must be the root. CATIProduct *piFatherProd = piProductOnObj -> GetFatherProduct(); piProductOnObj -> Release(); piProductOnObj = NULL; if (piFatherProd != NULL) { cout << "The caller is not the aggregating root product." << endl << flush; return S_OK; } else cout << "The caller is the aggregating root product: continue" << endl; ... |
This provider is active only if the caller is the Product
document's root object. In order to verify that this is the case, it is first
necessary to retrieve at CATIProduct pointer on the caller object. Then,
using the GetFatherProduct
, we can determine if the caller object
is the Product root by checking if it has a father. If it does not, it is itself
the Product root.
[Top]
2. Retrieve the applicative container.
... // Retrieve a pointer to the applicative container. CATILinkableObject *piLinkableOnObj = NULL; rc = pObj -> QueryInterface (IID_CATILinkableObject, (void**) &piLinkableOnObj); if (!SUCCEEDED(rc)) return E_FAIL; CATDocument* pDoc = piLinkableOnObj->GetDocument(); piLinkableOnObj -> Release(); piLinkableOnObj = NULL; CATUnicodeString appliContIdentifier("PstINFContainer"); CATBaseUnknown *pApplicativeContainer = NULL; rc = ::CATGetApplicativeContainer (&pApplicativeContainer, pDoc, IID_CATIContainer, appliContIdentifier); if (SUCCEEDED(rc)) cout << "Applicative container retrieved OK" << endl << flush; else { cout << "ERROR in retrieving applicative container" << endl << flush; return E_FAIL; } ... |
The first step in retrieving the root features that must be attached to the
Product root is to retrieve the applicative container. This is done using the CATGetApplicativeContainer
of the current document, whose CATDocument pointer is retrieved through
the GetDocument
method of CATILinkableObject.
[Top]
3. Retrieve the "CAAPstINFRoot" features from the applicative container.
... // Retrieve a pointer to CATIClientContainer in order to list the members // of the applicative container. CATIClientContainer *piClientOnAppliCont = NULL; rc = pApplicativeContainer -> QueryInterface(IID_CATIClientContainer, (void**) &piClientOnAppliCont); pApplicativeContainer -> Release(); pApplicativeContainer = NULL; if (NULL == piClientOnAppliCont) { cout << "ERROR in retrieving container pointer" << endl << flush; return E_FAIL; } else cout << "CATIClientContainer pointer retrieved OK" << endl << flush; // Retrieve the list of features in the applicative container CATUnicodeString clientId("CAAPstINFClientId"); CATListPtrCATBaseUnknown *pMemberList = NULL; rc = piClientOnAppliCont -> ListMembers(IID_CATISpecObject, clientId, &pMemberList); piClientOnAppliCont -> Release(); piClientOnAppliCont = NULL; if (SUCCEEDED(rc)) cout << "Member list retrieved OK" << endl << flush; else { cout << "ERROR in retrieving member list" << endl << flush; return E_FAIL; } cout << "Number of members in applicative container: " << pMemberList->Size() << endl; CATUnicodeString rootType(""); CATISpecObject *piSpecMember = NULL; for(int i=1;i<=pMemberList->Size();i++) { piSpecMember = (CATISpecObject *) (*pMemberList)[i]; rootType = piSpecMember -> GetType(); if (rootType == "CAAPstINFRoot") { (*pListChildren)->Append((*pMemberList)[i]); } (*pMemberList)[i] -> Release(); (*pMemberList)[i] = NULL; piSpecMember = NULL; } delete pMemberList; pMemberList = NULL; } return S_OK; } |
In order to retrieve a list of the features contained in the applicative
container, we need to get a CATIClientContainer pointer on it and execute
the ListMembers
method. Then, we can search through the returned
list of features and using the GetType
method of CATISpecObject,
we can append the features of type "CAAPstINFRoot" to the list to be
returned to the Product navigation implementation.
[Top]
Implementing CATINavigateObject on a New Feature Root
The CATINavigateObject interface is implemented on the feature root of type "CAAPstINFRoot". This interface has two methods:
GetIdentificators
- this method returns the display name of
the feature root object.GetChildren
- this method returns the list of the children
aggregated by the feature root object. 1. Implementing the GetIdentificators
method.
... CATListValCATUnicodeString * CAAEPstINFNavigateObjectRoot::GetIdentificators() { cout << "***** CAAEPstINFNavigateObjectRoot: CAAEPstINFNavigateObjectRoot::GetIdentificators" << endl; CATListOfCATUnicodeString *pIdent = new CATListOfCATUnicodeString; CATISpecObject *piSpecObjectOnRoot = NULL; HRESULT rc = this -> QueryInterface(IID_CATISpecObject, (void**)&piSpecObjectOnRoot); if (SUCCEEDED(rc)) { // Retrieve the root's name CATUnicodeString rootId = piSpecObjectOnRoot -> GetDisplayName(); piSpecObjectOnRoot -> Release(); piSpecObjectOnRoot = NULL; // String added to the list pIdent -> Append(rootId); } return pIdent; } ... |
This method returns the display name of the "CAAPstINFRoot" feature
root object. To do this, it first retrieves a CATISpecObject pointer on
the feature root ("this") and then executes the GetDisplayName
method in order to retrieve the display name which it appends to the returned
list.
[Top]
2. Implementing the GetChildren
method.
... CATListValCATBaseUnknown_var * CAAEPstINFNavigateObjectRoot::GetChildren() { cout << "***** CAAEPstINFNavigateObjectRoot::GetChildren" << endl; CATListValCATBaseUnknown_var *pList = NULL ; CATISpecAttrAccess *piAttrAccessOnRoot = NULL; HRESULT rc = this -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piAttrAccessOnRoot); if (FAILED(rc)) return pList; CATISpecAttrKey *piListComponentKey = NULL; piListComponentKey = piAttrAccessOnRoot -> GetAttrKey ("ListOfComponents"); if (!piListComponentKey) return pList; pList = new CATListValCATBaseUnknown_var(); CATISpecObject *piComponent = NULL; piAttrAccessOnRoot -> Beginning(piListComponentKey); while (piAttrAccessOnRoot -> Next(piListComponentKey)) { piComponent = piAttrAccessOnRoot -> GetSpecObject(piListComponentKey); if (NULL == piComponent) { cout << "Error in in retrieving component" << endl; piAttrAccessOnRoot -> Release(); piAttrAccessOnRoot = NULL; piListComponentKey -> Release(); piListComponentKey = NULL; return pList; } else cout << "Component retrieved OK" << endl; pList -> Append(piComponent); piComponent = NULL; } piAttrAccessOnRoot -> Release(); piAttrAccessOnRoot = NULL; piListComponentKey -> Release(); piListComponentKey = NULL; return pList; } ... |
This method returns a list of the features aggregated by the
"CAAPstINFRoot" feature root. To do this, it must first retrieve a CATISpecAttrAccess
pointer on the current object (feature root itself). Then, using the GetAttrKey
method, it retrieves the attribute key pointing to the list of aggregated
features. Using the Beginning
and Next
methods of CATISpecAttrAccess,
it scans through this list and retrieves every aggregated features using the GetSpecObject
method and appends the aggregated feature to the list to be returned to the
navigation caller.
[Top]
The CAAPstINFNavigate use case has shown you how new features created "from scratch" in an applicative container can be taken into account by the navigation process in order to integrate them in the product structure specs tree of a Product document. You have seen how to code a provider implementation corresponding to CATINavigateProvider and how to implement the CATINavigateObject interface for a new feature root object.
[Top]
[1] | The Object Navigator |
[2] | Initializing the Applicative Container at Runtime |
[Top] |
Version: 1 [June 2002] | Document created |
[Top] |
Copyright © 2002, Dassault Systèmes. All rights reserved.