3D PLM PPR Hub Open Gateway

Feature Modeler

The Build/Update Mechanism

Automatic updating of features
Use Case

Abstract

This article discusses the CAAOsmBuildUpdate use case. This use case explains the mechanism of the feature modeler's Build/Update, also called the "Feature Update Engine".


What You Will Learn With This Use Case

This use case is intended to help you understand the Build/Update mechanism of the feature modeler. Its main intent is to explain how to define build operations and how the update mechanism works by executing them and thus updating the features. More specifically, you will learn how to:

Before getting to the use case itself, it is important to get an understanding of what a feature object is, how it is created, as well as how the Build/Update Mechanism actually works [1].

[Top]

The CAAOsmBuildUpdate Use Case

CAAOsmBuildUpdate is a use case of the CAAObjectSpecsModeler.edu framework that illustrates ObjectSpecsModeler framework capabilities.

[Top]

What Does CAAOsmBuildUpdate Do

The CAAOsmBuildUpdate use case uses two feature StartUps, "CAAOsmAdd" and "CAAOsmSquare", that were created in the CAAOsmCatalogSU use case [2]. The features created from these StartUps, "CAAOsmAdd1" and "CAAOsmSquare1", are inter-related: When the values of the attributes of one are changed, the values of the attributes of the other must be updated. Here is what the two features look like:

Note that the sp_IN and sp_OUT keywords are attribute qualities that are set when the StartUp's attributes are initially defined. Their role has been explained in detail in the previous section.

The "Sum" attribute value is calculated from the values of the "First" and "Second" attributes which are both the input parameters of the CAAOsmAddOp Build operation. If you modify either value, the "CAAOsmAdd1" feature data will be inconsistent. To make your feature consistent, you must build it or rebuild it.

Now, let's focus on the "CAAOsmSquare1" feature. Its "Num" attribute points to the "Sum" attribute of "CAAOsmAdd1". Modifying either "First" or "Second" will require successively the rebuilding of the "CAAOsmAdd1" and "CAAOsmSquare1" features. Otherwise, the feature data will be inconsistent. Here is a schematic representation of how the update of the "CAAOsmSquare1" feature actually works:

[Top]

How to Launch CAAOsmBuildUpdate

To launch CAAOsmBuildUpdate, you will need to set up the build time environment, then compile CAAOsmBuildUpdate along with its prerequisites, set up the run time environment, and then execute the sample. 

mkrun -c "CAAOsmBuildUpdate CAAOsmCatalogSU.CATfct DocumentStorageName.CATPart"

This is fully described in the referenced article [3]. When launching the use case, you must pass the following arguments:

[Top]

Where to Find the CAAOsmBuildUpdate Code

CAAOsmCatalogSU code is located in the CAAOsmBuildUpdate.m use case module of the CAAObjectSpecsModeler.edu framework:

Windows InstallRootDirectory\CAAObjectSpecsModeler.edu\CAAOsmBuildUpdate.m
Unix InstallRootDirectory/CAAObjectSpecsModeler.edu/CAAOsmBuildUpdate.m

where InstallRootDirectory is the root directory of your CAA V5 installation. It is made of a unique source file named CAAOsmBuildUpdate.cpp.

[Top]

Step-by-Step

There are nine logical steps in CAAOsmBuildUpdate:

  1. Prolog
  2. Loading the Catalog
  3. Creating the CAAOsmAdd1 Feature
  4. Defining the Build Operation for CAAOsmAdd
  5. Creating the CAAOsmSquare1 Feature
  6. Defining the Build Operation for CAAOsmSquare
  7. Relating Attributes Between CAAOsmAdd1 and CAAOsmSquare1
  8. Updating CAAOsmquare1
  9. Epilog

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

[Top]

Prolog

See the referenced article [4] for a detailed description of the steps to go through when creating a new document.

In this use case, we create a new "Part" document: CATDocument *pDoc, and retrieve its root container: CATIContainer *piRootContainer.

[Top]

Loading the Catalog

Loading the catalog means opening the catalog document and getting a CATICatalog handle that will be needed in order to retrieve StartUps from the catalog.

CATUnicodeString stgName = argv[1];
CATICatalog *piCatalog;
CATUnicodeString clientId("CAAOsmClientId");
rc = ::AccessCatalog (&stgName,
                      &clientId,
	              piRootContainer,
		      &piCatalog); 
	
if (SUCCEEDED(rc)) cout << "Catalog accessed OK" << endl << flush;
else
{
   cout << "ERROR on AccessCatalog" << endl << flush;
   piRootContainer -> Release();
   return 5;
}

To open a catalog, use the AccessCatalog global function that takes the following arguments:

[Top]

Creating the Add1 Feature

  1. Retrieve "CAAOsmAdd" StartUp
    CATBaseUnknown *pAddSU = NULL;
    CATUnicodeString addSUType("CAAOsmAdd");
    rc = piCatalogOnContainer -> RetrieveSU(&pAddSU,
                                            &addSUType,
    	                               "CATISpecObject");
    if (NULL != pAddSU) cout << "CAAOsmAdd StartUp retrieved OK" << endl << flush;
    else
    {
       (Process ERROR:  Release pointers and return.)
    }
    
    // Get a CATISpecObject handle on the CAAOsmAdd StartUp
    
    CATISpecObject *piAddSU = (CATISpecObject*) pAddSU;

    The "CAAOsmAdd1" feature is an instance of the StartUp "CAAOsmAdd" of type "CAAOsmAdd" defined in the CAAOsmCatalogSU use case. In order to create it, we must first retrieve the StartUp from the catalog. A StartUp is retrieved from the catalog using the CATICatalog::RetrieveSU method. This method returns a CATBaseUnknown pointer in pAddSU which is directly cast into a CATISpecObject pointer (piAddSU).

  2. Get "CAAOsmAdd" StartUp's attribute keys
    CATISpecAttrAccess *piSpecAttrAccessOnAdd = NULL;
    rc = piAddSU -> QueryInterface(IID_CATISpecAttrAccess, 
                                   (void**) &piSpecAttrAccessOnAdd);
    if (FAILED(rc))
    {
       (Process ERROR:  Release pointers and return.)
    }
    
    CATISpecAttrKey *piKeyFirst = piSpecAttrAccessOnAdd ->
    		GetAttrKey("First");
    if (NULL == piKeyFirst)
    {
       (Process ERROR:  Release pointers and return.)
    }
    
    CATISpecAttrKey *piKeySecond = piSpecAttrAccessOnAdd ->
    		GetAttrKey("Second");
    if (NULL == piKeySecond)
    {
       Process ERROR:  Release pointers and return.)
    }
    
    CATISpecAttrKey *piKeySum = piSpecAttrAccessOnAdd -> 
    		GetAttrKey("Sum");
    if (NULL == piKeySum)
    {
       Process ERROR:  Release pointers and return.)
    }
    
    piSpecAttrAccessOnAdd -> Release();
  3. Instantiate "CAAOsmAdd" StartUp
    CATUnicodeString add1("CAAOsmAdd1");
    CATISpecObject *piAddInst1 = piAddSU -> 
    		Instanciate(add1,
    		            piRootContainer);
    pAddSU -> Release();
    if (NULL != piAddInst1) cout << "CAAOsmAdd instance created OK" << endl << flush;
    else
    {
       (Process ERROR:  Release pointers and return.)
    }

    We instantiate the StartUp to create the new feature "CAAOsmAdd1".

  4. Valuate "CAAOsmAdd1" attributes
    CATISpecAttrAccess *piSpecAttrAccessOnAdd1 = NULL;
    rc = piAddInst1 -> QueryInterface(IID_CATISpecAttrAccess,
                                      (void**) &piSpecAttrAccessOnAdd1);
    if (FAILED(rc))
    {
       (Process ERROR:  Release pointers and return.)
    }
    
    piSpecAttrAccessOnAdd1 -> SetInteger(piKeyFirst, 1);
    piSpecAttrAccessOnAdd1 -> SetInteger(piKeySecond, 2);
    piKeySecond -> Release();
    (... Continued after description of the "Add" Build operation.)

    We valuate "CAAOsmAdd1" attributes using a CATISpecAttrAccess handle on the new instance and the SetInteger method.

[Top]

Defining the Build Operation for CAAOsm Add (CAAOsmAddOp.cpp)

Defining the Build operation for the "CAAOsmAdd"-type feature means implementing the Build method of the CATIBuild interface. Note that in this use case, the CATIBuild implementation is a separate C++ file, but is included in the same load module as the main. No dictionary entry is, therefore, necessary. However, if CATIBuild were implemented in its own shared library, a dictionary entry would be necessary in order for the Build operation to be found and executed.

  1. Define interface implementation
    TIE_CATIBuild(CAAOsmAddOp);
    
    CATImplementClass(CAAOsmAddOp, 
    		  DataExtension,
                      CATBaseUnknown,
    		  CAAOsmAdd);
    
    HRESULT CAAOsmAddOp::Build()

    As for any interface implementation, the TIE and CATImplementClass commands are necessary in order to define the interface being implemented as a data extension of "CAAOsmAdd"-type features.

  2. Get current feature's attribute keys
    CATISpecAttrAccess *piSpecAttrAccessOnAdd = NULL;
    HRESULT rc = this -> QueryInterface(IID_CATISpecAttrAccess,
                                        (void**) &piSpecAttrAccessOnAdd);
    if (FAILED(rc))
    {
       cout << "ERROR in QueryInterface on CATISpecAttrAccess for CAAOsmAdd" << endl << flush;
       return 1;
    }
     
    CATISpecAttrKey *piKeyFirst = piSpecAttrAccessOnAdd -> 
    		GetAttrKey("First");
    if (NULL == piKeyFirst)
    {
       cout << "ERROR in retrieving First key" << endl << flush;
       return 2;
    }
    
    CATISpecAttrKey *piKeySecond = piSpecAttrAccessOnAdd ->
    		GetAttrKey("Second");
    if (NULL == piKeySecond)
    {
       cout << "ERROR in retrieving Second key" << endl << flush;
       return 2;
    }
    
    CATISpecAttrKey *piKeySum = piSpecAttrAccessOnAdd -> 
    		GetAttrKey("Sum");
    if (NULL == piKeySum)
    {
       cout << "ERROR in retrieving Sum key" << endl << flush;
       return 2;
    }

    What the Build operation for CAAOsmAdd does is to simply retrieve the values of its input attributes, add them together and store the resulting value in its output attribute. In order to retrieve the attributes, it needs to get a CATIAttrAccess handle using the this pointer and uses it to retrieve the attribute keys using GetAttrKey.

  3. Retrieve and valuate attributes
    int f = 0;
    int s = 0;
    f = piSpecAttrAccessOnAdd -> GetInteger(piKeyFirst);
    s = piSpecAttrAccessOnAdd -> GetInteger(piKeySecond);
    piSpecAttrAccessOnAdd -> SetInteger(piKeySum, f+s);
    int printVal = 0;
    printVal = piSpecAttrAccessOnAdd -> GetInteger(piKeySum);
    cout << "The value of sum is " << printVal << endl << flush;
    
    piSpecAttrAccessOnAdd -> Release();
    piKeyFirst -> Release();
    piKeySecond -> Release();
    piKeySum -> Release();

    Now, using the keys, we retrieve the values of "First" and "Second" using the GetInteger method, add them together, and store the resulting value in "Sum" attribute using SetInteger.

    Note that the pointers acquired through GetAttrKey must be released when no longer needed!

    The update of "Sum" also updates the value of "Num" in the Square feature, as you will see a little later.

[Top]

Creating the CAAOsmSquare1 Feature

The "CAAOsmSquare1" feature is also an instance of the StartUp defined in the CAAOsmCatalogSU use case.

  1. Retrieve "CAAOsmSquare" StartUp
    (... Continued)
    CATBaseUnknown *pSquareSU = NULL;
    CATUnicodeString squareSUType("CAAOsmSquare");
    rc = piCatalogOnContainer -> RetrieveSU(&pSquareSU,
                                            &squareSUType,
    	                               "CATISpecObject");
    piCatalogOnContainer -> Release();
    if (NULL != pSquareSU) cout << "CAAOsmSquare StartUp retrieved OK" << endl << flush;
    else
    {
       (Process ERROR:  Release pointers and return.)
    }
    // Get a CATISpecObject handle on the CAAOsmSquare StartUp
    
    CATISpecObject *piSquareSU = (CATISpecObject*) pSquareSU;

    As with the "CAAOsmAdd1" feature, in order to create a new feature, we must first retrieve the StartUp from the catalog using the RetrieveSU method and get a CATISpecObject handle on the StartUp.

  2. Get "CAAOsmSquare" StartUp's attribute keys
    CATISpecAttrAccess *piSpecAttrAccessOnSq = NULL;
    rc = piSquareSU -> QueryInterface(IID_CATISpecAttrAccess, 
                                      (void**) &piSpecAttrAccessOnSq);
    if (FAILED(rc))
    {
       (Process ERROR:  Release pointers and return.)
    }
     
    CATISpecAttrKey *piKeyNum = piSpecAttrAccessOnSq -> 
    		GetAttrKey("Num");
    if (NULL == piKeyNum)
    {
       (Process ERROR:  Release pointers and return.)
    }
    
    CATISpecAttrKey *piKeySquare = piSpecAttrAccessOnSq ->
    		GetAttrKey("Square");
    if (NULL == piKeySquare)
    {
       (Process ERROR:  Release pointers and return.)
    }
    	  
    piSpecAttrAccessOnSq -> Release();

    Now, before actually creating the new feature, we get the attribute keys from the StartUp.

  3. Instantiate "CAAOsmSquare" StartUp
    CATUnicodeString square1("CAAOsmSquare1");
    CATISpecObject *piSqInst1 = piSquareSU ->
    		Instanciate(square1,
    		            piRootContainer);
    piRootContainer -> Release();
    pSquareSU -> Release();
    if (NULL != piSqInst1) cout << "CAAOsmSquare instance created OK" << endl << flush;
    else
    {
       (Process ERROR:  Release pointers and return.)
    }
    (... Continued after description of the "Square" Build operation.)

    Finally, we can instantiate the StartUp to create the new feature "CAAOsmSquare1".

[Top]

Defining the Build Operation for CAAOsmSquare (CAAOsmSquareOp.cpp)

  1. Define interface implementation
    TIE_CATIBuild(CAAOsmSquareOp);
    
    CATImplementClass(CAAOsmSquareOp,
    		  DataExtension,
                      CATBaseUnknown,
    		  CAAOsmSquare);
    
    HRESULT CAAOsmSquareOp::Build()

    As for any interface implementation, the TIE and CATImplementClass commands are necessary in order to define the interface being implemented as a data extension of "CAAOsmSquare"-type features.

  2. Get current feature's attribute keys
    CATISpecAttrAccess *piSpecAttrAccessOnSquare = NULL;
    HRESULT rc = this -> QueryInterface(IID_CATISpecAttrAccess,
                                        (void**) &piSpecAttrAccessOnSquare);
    if (FAILED(rc))
    {
       cout << "ERROR in QueryInterface on CATISpecAttrAccess for CAAOsmSquare" << endl << flush;
       return 1;
    }
     
    
    CATISpecAttrKey *piKeyNum = piSpecAttrAccessOnSquare ->
    		GetAttrKey("Num");
    if (NULL == piKeyNum)
    {
       cout << "ERROR in retrieving Num key" << endl << flush;
       return 2;
    }
    
    CATISpecAttrKey *piKeySquare = piSpecAttrAccessOnSquare -> 
    		GetAttrKey("Square");
    if (NULL == piKeySquare)
    {
       cout << "ERROR in retrieving Square key" << endl << flush;
       return 2;
    }

    What the Build operation for "CAAOsmSquare" does is to simply retrieve the value of its input attribute, "Num", squares it and stores the result in its output attribute, "Square". In order to retrieve the attributes, it needs to get a CATIAttrAccess using the this pointer and uses it to retrieve the attribute keys using GetAttrKey.

  3. Retrieve and valuate attributes
    int val = 0;
    val = piSpecAttrAccessOnSquare -> GetInteger(piKeyNum);
    piSpecAttrAccessOnSquare -> SetInteger(piKeySquare, val*val);
    ...	
    piSpecAttrAccessOnSquare -> Release();
    piKeyNum -> Release();
    piKeySquare -> Release();

    Using the keys, we retrieve the value of "Num" (which is based on the value of "Sum" from CAAOsmAdd) using GetInteger, we square it, and store the resulting value in the "Square" attribute using SetInteger.

    Do not forget to release the pointers!

[Top]

Relating Attributes Between CAAOsmAdd1 and CAAOsmSquare1

CATISpecAttrAccess *piSpecAttrAccessOnSq1 = NULL;
rc = piSqInst1 -> QueryInterface(IID_CATISpecAttrAccess, 
                                 (void**) &piSpecAttrAccessOnSq1);
if (FAILED(rc))
{
   (Process ERROR:  Release pointers and return.)
}

piSpecAttrAccessOnSq1->SetSpecAttribute(piKeyNum,
		                        piAddInst1,
					piKeySum);

piAddInst1 -> Release();
piKeySum -> Release();
piKeyNum -> Release();

The attribute "Num" of the "CAAOsmSquare1" feature depends on the value of the attribute "Sum" of the "CAAOsmAdd1" feature. In order to define this relationship, we must set the one to be equal to the other. This is done by SetSpecAttribute using a CATISpecAttrAccess handle on the "CAAOsmSquare1" feature and referencing the "CAAOsmAdd1" feature, the "CAAOsmAdd1" attribute key "Sum" and the "CAAOsmSquare1" attribute key "Num" as parameters:

[Top]

Updating CAAOsmSquare1

Now that the features have been created and their Build operations defined, let's see what happens when an Update is requested on the "CAAOsmSquare1" feature:

Here is how to update the "CAAOsmSquare1" feature:

...	
piSqInst1 -> Update();
...

To update the "CAAOsmSquare1" feature, use the Update method of CATISpecObject

[Top]

Epilog

Before saving the document, release all of the pointers that will no longer be used:

piUpdateOnSqInst1 -> Release();

piSpecAttrAccessOnSq1 -> Release();

piKeySquare -> Release();

See the referenced article [4] for a detailed description of the steps to go through when saving a document.

[Top]


In Short

This use case has demonstrated how the Build/Update mechanism works and how to use it to update one's features. Specifically, it has illustrated:

[Top]


References

[1] Feature Modeler Overview
[2] Creating StartUps in Catalogs
[3] Building and Launching a CAA V5 Use Case
[4] Creating a New Document
[Top]

History

Version: 1 [Feb 2000] Document created
Version: 2 [Nov 2000] Document modified
[Top]

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