3D PLM PPR Hub Open Gateway

Product Modeler

Using the Provider Mechanism

Navigating through applicative containers and feature extensions

Use Case

Abstract

This article discusses the CAAPstProviders use case. This use case explains how to use the Product Modeler's "Providers" mechanism to integrate applicative data in the native behaviors of a Product document.


What You Will Learn With This Use Case

This use case is intended to help you understand how to work with the Provider mechanism of the Product Modeler. The Provider mechanism allows an application to be integrated in the native behaviors of a product structure. For example, a product structure may not be aware of the specific contents of each applicative container or feature extension found in the Product document and yet still be capable of taking these into account when performing native tasks, such as navigation or visualization. Currently, four provider interfaces have been defined:

  1. CATINavigateProvider is the provider interface corresponding to CATINavigateObject of the ObjectModelerBase framework.
  2. CATI3DVisuProvider is the provider interface corresponding to CATI3DGeoVisu of the Visualization framework.
  3. CATICtxMenuProvider is the provider interface corresponding to CATIUIActivate of the ApplicationFrame framework.
  4. CATIParmProvider is the provider interface corresponding to CATIParmPublisher of the LiteralFeatures framework.

The implementation of any one of these interfaces is the actual provider. Each provider supports a specific algorithm. When a provider declaration is currently active, the implementation of the corresponding interface calls the method implemented by the provider. In this use case, you will see how to create and declare a provider in order to integrate one of the native behaviors listed above.

[Top]

The CAAPstProviders Use Case

CAAPstProviders is a use case of the CAAProductStructure.edu framework that illustrates ProductStructure framework capabilities.

[Top]

What Does CAAPstProviders Do

The goal of CAAPstProviders is to illustrate working with the Providers mechanism. The example illustrated by this use case deals with CATINavigateProvider implementations. However, the provider mechanism shown here is valid for all the other provider interfaces listed in the previous section.

The CAAPstProviders use case uses two files that must be found in the runtime view when executing the use case: "CAAPstExtCatalog.CATfct" and "CAAPstProvider.CATProduct". 

The "CAAPstExtCatalog.CATfct" file contains the following extension definition:

Fig.1 CAAPstExtCatalog.CATfct

The "CAAPstProvider.CATProduct" document structure can be viewed in two different ways, depending on whether we want to see it from a data storage view or from an interactive session view. The reason for this is that Provider declarations and extensions activations are not persistent tasks, i.e., they are not saved within the document data stream during the save operation. Therefore, relationships between applicative data may only be established during an interactive session. 

Following is the contents of the document as seen from a data storage view:

Fig. 2 CAAPstProvider.CATProduct - Data StorageView

Now, here is the image of the same document's contents after it has been loaded in an interactive session:

Fig. 3 CAAPstProvider.CATProduct - Interactive View

Note that the applicative containers are not displayed in the navigation tree. Likewise, feature attributes that do not themselves point to other features are not displayed in the navigation tree either. What we do see in the navigation tree is that the "CAAOsmBook1" feature is aggregated by the "CAAPstProviderSubProduct1" and that it has a child called "CAAOsmChapter1" which is itself a feature actually aggregated by an extension of "CAAOsmBook1".

Now, let's try to understand how the mechanism works. As you can see by looking at the structure of the document in storage, the root product aggregates a sub-product. However, the sub-product does not directly aggregate the contents of the "CAAPstBFCont" applicative container as shown in the Interactive View. In order for the sub-product to aggregate the contents of "CAAPstBFCont", the implementation of CATINavigateObject on the product must return the children of "CAAPstBFCont": this is done using a provider. 

Likewise, notice that the "CAAOsmChapter1" feature is not a direct child of "CAAOsmBook1", but rather the child of the extension of "CAAOsmBook1" called "CAAPstHistoricalNovel1". Because "CAAOsmBook1" does not necessarily know what, if any, extensions have been activated on it, it cannot retrieve its extensions' children directly from the CATINavigateObject implementation. A provider created especially for this purpose must be declared instead. 

To summarize, then, the two objects implementing CATINavigateObject must call specific providers in order to aggregate certain children they have no specific knowledge of. 

Providers themselves are called in a generic fashion. In other words, they are first declared to the document. Then, during the CATINavigateObject implementation(s), the list of active providers is retrieved and each provider is called in turn. It is within the provider code itself to determine the identity of the parent caller in order to retrieve the children of the specific object it is a provider for.

You will see in the details of the use case how this is actually done. But first, take a look at the diagram below representing the navigation process illustrated by this use case:

Fig. 4 CAAPstProviders Navigation Process

[Top]

How to Launch CAAPstProviders

To launch CAAPstProviders, you will need to set up the build time environment, then compile the following modules:

Furthermore, verify that the runtime view contains:

Now, you will need to set up the runtime environment, and then launch a CATIA session. This is fully described in the referenced article [1]. To launch the use case, simply select "File/Open" and open the CAAPstProvider.CATProduct document found in the resources + graphic runtime directory.

[Top]

Where to Find the CAAPstProviders Code

The main CAAPstProviders code is found in the CAAProductStructure.edu framework. It is composed of four modules as follows:

Windows InstallRootDirectory\CAAProductStructure.edu\CAAPstEduContInit.m, CAAPstEduNavigBook.m, CAAPstEduNavigExtProv.m, CAAPstEduNavigFeatProv.m and CAAPstEduCtxMenuProv.m
Unix InstallRootDirectory/CAAProductStructure.edu/CAAPstEduContInit.m, CAAPstEduNavigBook.m, CAAPstEduNavigExtProv.m, CAAPstEduNavigFeatProv.m and CAAPstEduCtxMenuProv.m

where InstallRootDirectory is the root directory of your CAA V5 installation.

[Top]

Step-by-Step

There are four logical steps in CAAPstProviders:

  1. Implementing CATINavigateProvider for the First Sub-Product
  2. Implementing CATINavigateProvider for the "CAAOsmBook" Feature's Extension
  3. Implementing CATInit for the "CAAPstBFCont" Aplicative Container
  4. Implementing CATINavigateObject for the "CAAOsmBook" feature
  5. Implementing CATICtxMenuProvider for the First Sub-Product

We will now comment each of these sections by looking at the code. 

[Top]

Implementing CATINavigateProvider for the First Sub-Product

The provider implementation that returns the list of the children of the "CAAPstBFCont" applicative container is found in the CAAPstAppliContProvider.cpp file of the CAAPstEduNavigFeatProv.m module. It is an implementation class on the CATINavigateProvider interface for a CATNull late type. In other words, no dictionary entry is necessary. This provider implements the GetChildren method defined by the CATINavigateProvider interface. However, it only returns the list of children if the parent caller is the sub-product called "CAAPstProviderSubProduct1". 

Remember that the CATINavigateProvider implementations are called regardless of the current object. In other words, the CATINavigateObject implementation on "Product1" or on "CAAPstProviderSubProduct1" is the same so that the same provider will be called for each: It is the provider's responsibility to return the list of children depending on the proper parent. 

1. Verify that the parent caller is "CAAPstProviderSubProduct1.1"

HRESULT CAAPstAppliContProvider::GetChildren(CATBaseUnknown * pObj, CATLISTP(CATBaseUnknown) ** pListChildren) 
{
    cout << "***** CAAPstAppliContProvider::GetChildren" << endl << flush;

    // This provider returns the list of the children found in the applicative
    // container of the document only if the caller is the subproduct 
    // named "CAAPstProviderSubProduct1.1"

    // Retrieve a CATIProduct handle on the caller object
    CATIProduct *piProductOnObj = NULL;
    HRESULT rc = pObj -> QueryInterface (IID_CATIProduct, 
	                                (void**) &piProductOnObj);
    if (SUCCEEDED(rc))
    {
	// Retrieve the name of the product caller; if it is "CAAPstProviderSubProduct1.1"
	// then create and return the list of the children of the applicative container.
	CATUnicodeString productName;
	rc = piProductOnObj -> GetPrdInstanceName(productName);
	piProductOnObj -> Release();
	piProductOnObj = NULL;
	if (productName != "CAAPstProviderSubProduct1.1")
	{
	    cout << "The caller is not the aggregating subproduct." << endl << flush;
	    return S_OK;
	}
...   

The parent caller is passed as an argument to the GetChildren method (pObj). If a CATIProduct pointer can be retrieved on it, then use the GetPrdInstanceName method to retrieve its name. If the product's name is "CAAPstProviderSubProduct1.1", then it is the proper parent under which we want to list the contents of the base feature applicative container. Otherwise, we return to the calling GetChildren method.

[Top]

2. Retrieve the base feature 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("BaseFeatureContainer");
          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;
          }

          // 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;
...

In order to retrieve a pointer to the applicative container, a CATDocument pointer is necessary. This pointer can be retrieved using the CATILinkableObject::GetDocument method on the parent caller. Then, the CATGetApplicativeContainer global function can be executed, using the applicative container identifier as argument. Now, acquire a CATIClientContainer pointer on the applicative container to be used in order to list the members of the container.

[Top]

3. Construct the list of the direct children of the sub-product (features of the applicative container).

...
          // Retrieve the list of features in the applicative container
          CATUnicodeString clientId("CAAOsmClientId"); 
          CATListPtrCATBaseUnknown *pMemberList = new CATListPtrCATBaseUnknown();
          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 << flush;
      
          for(int i=1;i<=pMemberList->Size();i++)
          {
	    (*pListChildren)->Append((*pMemberList)[i]);
          }
          delete pMemberList;
          pMemberList = NULL;
      }

      return S_OK;
}

Use the ListMembers method of CATIClientContainer to list the members of type CATISpecObject found in the applicative container. Then, loop through this list and append each member to the list of children to be returned.

[Top]

Implementing CATINavigateProvider for the "CAAOsmBook" Feature's Extension

The provider implementation that returns the list of the children of the "CAAOsmBook1" feature is found in the CAAPstBookExtProvider.cpp file of the CAAPstEduNavigExtProv.m module. It is an implementation class on the CATINavigateProvider interface for a CATNull late type. In other words, no dictionary entry is necessary. This provider implements the GetChildren method defined by the CATINavigateProvider interface. However, it only returns the list of children if the parent caller is the "CAAOsmBook1" feature: it knows that an extension aggregating another feature instance on the "NovelChapter" attribute may be active.

Remember that the CATINavigateProvider implementations are called regardless of the current object. In other words, the CATINavigateObject implementation on "CAAOsmBook" will call all of the providers that may be currently active,  whether or not they are pertinent to the "CAAOsmBook1" feature. 

1. Verify that the parent caller is "CAAOsmBook1".

HRESULT CAAPstBookExtProvider::GetChildren(CATBaseUnknown * pObj, CATLISTP(CATBaseUnknown) ** pListChildren) 
{
   cout << "***** CAAPstBookExtProvider::GetChildren" << endl << flush;

   // This provider returns the children of the extension of the feature named
   // "CAAOsmBook1". If the caller object is not this feature, the provider
   // simply returns.

   // Retrieve a CATISpecObject pointer on the caller object.
   CATISpecObject *piSpecObjectOnExtFeature = NULL;
   HRESULT rc = pObj -> QueryInterface (IID_CATISpecObject,
		                     (void**) &piSpecObjectOnExtFeature);

   if (!SUCCEEDED(rc)) return S_OK;

   CATUnicodeString specName = piSpecObjectOnExtFeature -> GetName();
   if (specName == "CAAOsmBook1")
   {     
      ...

Retrieve a CATISpecObject pointer on the parent caller. If the pointer is correctly retrieved, use the GetName method to test whether the parent caller is actually the "CAAOsmBook1" feature, thus being applicable to this provider.

[Top]

2. Retrieve and return the value of the "NovelChapter" attribute.

...
      // Retrieve CATIOsmExtendable on the base feature
      CATIOsmExtendable *piExtendableOnExtFeature = NULL; 
      rc = piSpecObjectOnExtFeature -> QueryInterface(IID_CATIOsmExtendable, 
                                                      (void**) &piExtendableOnExtFeature); 
      piSpecObjectOnExtFeature -> Release(); 
      piSpecObjectOnExtFeature = NULL; 
      if (FAILED(rc)) return E_FAIL; 

      // Retrieve CATISpecAttrAccess on the extension
      const char *extensionName = "CAAPstHistoricalNovel"; 
      CATISpecAttrAccess *piAccessOnExtension = NULL; 
      rc = piExtendableOnExtFeature->QueryExtension(extensionName, 
                                                    IID_CATISpecAttrAccess, 
                                                    (void**) &piAccessOnExtension); 
      piExtendableOnExtFeature->Release(); 
      piExtendableOnExtFeature = NULL; 
      if (FAILED(rc)) return E_FAIL; 

      // Retrieve the attribute key for the extensions component attribute
      CATISpecAttrKey *piKeyNovelChapter = piAccessOnExtension -> GetAttrKey("NovelChapter"); 
      if (NULL == piKeyNovelChapter) return E_FAIL; 

      // Retrieve the feature value of the attribute
      CATBaseUnknown *pChapter = NULL; 
      pChapter = piAccessOnExtension -> GetSpecObject (piKeyNovelChapter, 1); 
      piAccessOnExtension -> Release(); 
      piAccessOnExtension = NULL; 
      piKeyNovelChapter -> Release(); piKeyNovelChapter = NULL; 

      // Add the feature to the list of children 
      if (NULL != pChapter) { 
         if (NULL == *pListChildren) 
            *pListChildren = new CATLISTP(CATBaseUnknown); 
         (*pListChildren)->Append(pChapter); 
      } else 
         return E_FAIL;
...

To get an attribute value on the "CAAPstHistoricalNovel" extension, we first need to retrieve a CATISpecAttrAccess pointer on the extension itself. This is done by retrieving a CATIOsmExtendable pointer on the feature and then use it to query for a "CAAPstHistoricalNovel" extension, to be returned as a CATISpecAttrAccess pointer.

With this CATISpecAttrAccess pointer on the extension, get the attribute key with the GetAttrKey method for the "NovelChapter" attribute, and then use the GetSpecObject method to retrieve a pointer to the aggregated feature. It is this feature that is appended to the list of the children of the "CAAOsmBook1" parent.

[Top]

Implementing CATInit for the "CAAPstBFCont" Applicative Container

The implementation of the CATInit interface on the "CAAPstBFCont" applicative container is found in the CAAEPstInit.cpp source code of the CAAPstEduContInit.m module. It is called upon the selection of the File/Open command when the CAAPstProvider.CATProduct document is loaded into the interactive session. Implementing this interface is necessary because, as you have already seen, provider declarations and extensions activation are not persistent operations, i.e., they are not saved with the document and must, therefore, be re-initialized at the start of an interactive session.

1. Retrieve the current document.

void CAAEPstInit::Init (CATBoolean iDestroyExistingData)   
  {
     cout << "***** CAAPstBFCont: CAAEPstInit::Init" << endl << flush;
     // 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;     

The current document is retrieved using the GetDocument method of CATILinkableObject, a pointer to which is acquired on the current object (the applicative container) using QueryInterface.

[Top]

2. Declare Providers.

    // Retrieve a CATIProviders pointer on the current document
    CATIProviders *piProvidersOnDocument = NULL;
    rc = pDoc -> QueryInterface(IID_CATIProviders,
                                (void**) &piProvidersOnDocument);
    if (!SUCCEEDED(rc)) return;

    // Declare provider to list the children of the applicative container 
    CAAPstAppliContProvider *pAppliContProvider = new CAAPstAppliContProvider();
    rc = piProvidersOnDocument -> AddProvider (IID_CATINavigateProvider,
	                                       pAppliContProvider);
    if (!SUCCEEDED(rc)) return;
    else cout << "Applicative container provider declared OK" << endl;

    // Declare provider for the contextual menu
    CAAPstCtxMenuProvider *pCtxMenuProvider = new CAAPstCtxMenuProvider(); 
    rc = piProvidersOnDocument -> AddProvider (IID_CATICtxMenuProvider,
                                               pCtxMenuProvider);
    ...
    if (!SUCCEEDED(rc)) return; 
    else cout << "Applicative container provider declared OK" << endl; 

    // Declare provider to list the children of an extended feature
    CAAPstBookExtProvider *pBookExtProvider = new CAAPstBookExtProvider();
    rc = piProvidersOnDocument -> AddProvider (IID_CATINavigateProvider,
	                                      pBookExtProvider);
    ...
    if (!SUCCEEDED(rc)) return;
    else cout << "Extended feature provider declared OK" << endl;

Providers are declared on a CATDocument object using the CATIProviders::AddProvider method of ProductStructure. A CATIProviders pointer must, therefore, be acquired on the current document. Then, each provider class is first instantiated and then declared to the document using the AddProvider method. This method takes as a first argument the name of the provider interface, in this case CATINavigateProvider, and in the second argument the pointer to the provider class instance. Remember that the provider declaration is not persistent: if the document is re-opened in another CATIA session, these provider declarations will no longer be active.

[Top]

3. Activate extensions

     // Activate extensions (only required for former extensions) 
     const char *appliContIdentifier = "ExtensionContainer"; 
     rc = CATOsmExtensionServices::CATActivateExtensions(pDoc, 
                                                         appliContIdentifier); 
     if (FAILED(rc)) { 
        cout << "ERROR activating extensions" << endl; 
        return ; 
     } else 
        cout << "Extensions activated OK" << endl; 

     return;
  }

The last task to be executed by the Init method is to activate the former extensions of the document. Please note that this step is only required for former extensions as newer extensions are always active. This is done by calling the CATActivateExtensions method of the CATOsmExtensionServices class with a CATDocument pointer on the document and the container name "ExtensionContainer".

Now, all the providers and extensions needed are active. During the display process, the navigation tree will be constructed by calling the existing implementations of CATINavigateObject for each late type encountered. 

[Top]

Implementing CATINavigateObject for the "CAAOsmBook" Feature

The implementation of CATINavigateObject for the "CAAOsmBook" late type is found in the CAAEPstNavigateObject.cpp source file of the CAAPstEduNavigBook.m module.In this implementation, you will see that several providers are actually called but only one is valid for the "CAAOsmBook" parent type. As you saw in the previous sections, the provider caller is not responsible for knowing whether the provider being called is relevant for the given parent type.

1. List the active providers.

CATListValCATBaseUnknown_var * CAAEPstNavigateObject::GetChildren()
{
  cout << "***** CAAOsmBook: CAAEPstNavigateObject::GetChildren" << endl;

  CATListValCATBaseUnknown_var *pList = NULL ;
  pList = new CATListValCATBaseUnknown_var();
  
  // Retrieve the list of declared providers

  CATLISTP(CATBaseUnknown) *pListProvider = new CATLISTP(CATBaseUnknown);
  CATLISTP(CATBaseUnknown) *pListChildren = NULL;

  // Retrieve a CATILinkableObject pointer on the CAAOsmBook feature in order
  // to get a CATDocument pointer to the document which contains it.
  CATILinkableObject * piLinkableOnExtFeature = NULL;
  HRESULT rc = this -> QueryInterface (IID_CATILinkableObject,
	                              (void**) &piLinkableOnExtFeature);
  if (!SUCCEEDED(rc)) return pList;

  CATDocument *pDoc = piLinkableOnExtFeature -> GetDocument();
  piLinkableOnExtFeature -> Release();
  piLinkableOnExtFeature = NULL;
  if (NULL == pDoc) return pList;

  // Retrieve a CATIProviders pointer on the document.
  CATIProviders * piProvidersOnDoc = NULL;
  rc = pDoc -> QueryInterface (IID_CATIProviders,
	                      (void**) &piProvidersOnDoc);
  if (!SUCCEEDED(rc)) return pList;

  // Retrieve a list of the providers that have been declared to the document.
  rc = piProvidersOnDoc -> ListProviders (CATINavigateProvider::ClassId(),
	                                 &pListProvider);
  piProvidersOnDoc -> Release();
  piProvidersOnDoc = NULL;
...

First of all, it is necessary to initialize the different array variables for the different lists of providers and children that will be retrieved. Then, using the "this" pointer, get a CATDocument pointer to the document in which "this" is contained using the GetDocument method of CATILinkableObject. Now, using the CATDocument pointer, we can get a pointer to CATIProviders and execute the ListProviders method to retrieve a list of all of the providers declared to the document for the CATINavigateProvider interface.

[Top]

2. Construct the list of children retrieved from every active provider.

...
  // For each declared provider, get the CATINavigateProvider interface pointer to
  // execute the GetChildren method and append the list of children returned to the
  // list to be constructed.

  if(SUCCEEDED(rc))
  {
     int size = pListProvider->Size();
     for (int i=size; i>=1; i--)
     {
	// Retrieve a CATINavigateProvider pointer on the provider
	CATINavigateProvider *piNav = NULL;
	rc = (*pListProvider)[i] -> QueryInterface(IID_CATINavigateProvider,
		                                  (void**) &piNav);
	if (SUCCEEDED(rc))
	{
	    pListChildren = new CATLISTP(CATBaseUnknown);
	    // Retrieve the list of the children of the current object 
	    piNav -> GetChildren (this, &pListChildren);
 	    if (NULL != pListChildren)
	 	for(int j=1;j<=pListChildren->Size();j++)
		{
		   if((*pListChildren)[j])
		   {
		       // Append the child to the list being constructed.
	    	       CATINavigateObject_var navChild ((*pListChildren)[j]);
		       if(navChild!=NULL_var)
			 pList->Append(navChild);
			 (*pListChildren)[j]->Release();
		  }
	         }
	    delete pListChildren;
	    pListChildren = NULL;
	    piNav->Release();
	 }
     }
     delete pListProvider;
  }
  return pList;
}

If the list of providers has correctly been retrieved, loop through the list and call the GetChildren method of each provider. (Remember that the provider will return a valuated list of children depending on the identity of the parent caller.) Then, if the list of children is not null, each child is appended to the actual list of children that will be returned to the navigator.

[Top]

Implementing CATICtxMenuProvider for the First Sub-Product

The provider implementation that adds a contextual menu entry labeled "CAACtxMenuCmd" is in the CAAPstCtxMenuProvider.cpp file of the CAAPstEduCtxMenuProv.m module. It is an implementation class on the CATICtxMenuProvider interface for a CATNull late type. In other words, no dictionary entry is necessary. This provider implements the GetContextualMenu method defined by the CATICtxMenuProvider interface. However, it only creates a contextual menu entry if the caller is the sub-product named "CAAPstProviderSubProduct1.1". 

...

HRESULT CAAPstCtxMenuProvider::GetContextualMenu(CATBaseUnknown *iObj,
						 CATCmdContainer *oCtxMenu)
{
	// Retrieve a CATIProduct handle on the caller object
	CATIProduct *piProductOnObj = NULL;
	if (NULL == iObj) return E_FAIL;
	HRESULT rc = iObj -> QueryInterface (IID_CATIProduct, 
					     (void**) &piProductOnObj);
	if (SUCCEEDED(rc)) {
		// Retrieve the name of the product caller
		// If it is "CAAPstProviderSubProduct1.1"
		// then create a entry in the contextual menu
		CATUnicodeString productName;
		rc = piProductOnObj->GetPrdInstanceName(productName);
		piProductOnObj->Release();
		piProductOnObj = NULL;
		if (productName == "CAAPstProviderSubProduct1.1") {
			NewAccess(CATCmdStarter, pStarter, CAACtxMenuStarter);
			CATString cmdName("CAACtxMenuCmd");
			SetAccessCommand(pStarter, cmdName);
			SetAccessChild(oCtxMenu, pStarter);
			return S_OK;
		}
	}
	return E_FAIL;
}
...

The purpose of this implementation is to illustrate the CATICtxMenuProvider interface and as such does not provide any meaningful user interaction. Please consult this article [2] for more information on contextual menus.

Fig. 5 CATICtxMenuProvider implementation

[Top]


In Short

A Provider is an implementation class of one of the supplied provider interfaces. It is declared to the document at runtime. The implementations of native interfaces use active providers to complement their behaviors: in other words, providers will return specific information on applicative data that the parent caller object has no direct knowledge of.

[Top]


References

[1] Building and Launching a CAA V5 Use Case
[2] Inserting Commands in Contextual Menus
[Top]

History

Version: 3 [Jul 2004] CATICtxMenuProvider Added
Version: 2 [Feb 2004] CATIIconProvider Removed
Version: 1 [May 2001] Document created
[Top]

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