3D PLM PPR Hub Open Gateway |
Feature Modeler |
The Build/Update MechanismAutomatic updating of features |
Use Case |
AbstractThis 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". |
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]
CAAOsmBuildUpdate is a use case of the CAAObjectSpecsModeler.edu framework that illustrates ObjectSpecsModeler framework capabilities.
[Top]
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]
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]
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]
There are nine logical steps in CAAOsmBuildUpdate:
CAAOsmAdd1
FeatureAdd
CAAOsmSquare1
FeatureCAAOsmSquare
CAAOsmAdd1
and CAAOsmSquare1
CAAOsmquare1
We will now comment each of those sections by looking at the code.
[Top]
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 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:
stgName
- the name of the catalog without the storage path
and with the .CATfct extension. The catalog must be found under the
"WS" + "OS" + resources + graphic directory.clientId
- the client id defined on the catalog at the time
of its creation.piRootContainer
- a CATIContainer pointer to the
container in which StartUps from the catalog will be instantiated.piCatalog
- a CATICatalog pointer to the StartUps
catalog that has been opened.[Top]
Add1
Feature
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
).
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(); |
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".
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]
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.
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.
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
.
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]
Square1
FeatureThe "CAAOsmSquare1" feature is also an instance of the StartUp defined in the CAAOsmCatalogSU use case.
(... 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.
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.
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]
Square
(CAAOsmSquareOp.cpp)
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.
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
.
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]
Add1
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]
Square1
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:
sp_IN
attribute
of the CAAOsmSquare
feature.CAAOsmAdd1
"
feature because it is the owner of the "Sum" sp_OUT
attribute.CAAOsmAdd1
" feature, the sp_IN
attributes "First" and "Second" are requested to
update: the "CAAOsmAdd
" Build operation is executed.
"Sum" is set a value resulting from the "CAAOsmAdd
"
Build and its update stamp is modified.CAAOsmSquare
"
Build as "Num" is an sp_IN
attribute.CAAOsmSquare1
" feature is built and the value
of "Square" is set by the "CAAOsmSquare
"
Build result.Here is how to update the "CAAOsmSquare1" feature:
... piSqInst1 -> Update(); ... |
To update the "CAAOsmSquare1" feature, use the Update
method of CATISpecObject.
[Top]
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]
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:
Update
method of CATISpecObject.[Top]
[1] | Feature Modeler Overview |
[2] | Creating StartUps in Catalogs |
[3] | Building and Launching a CAA V5 Use Case |
[4] | Creating a New Document |
[Top] |
Version: 1 [Feb 2000] | Document created |
Version: 2 [Nov 2000] | Document modified |
[Top] |
Copyright © 2000, Dassault Systèmes. All rights reserved.