3D PLM PPR Hub Open Gateway |
Feature Modeler |
Referencing Features by FeaturesWorking with referenced attributes |
Use Case |
AbstractThis article discusses the CAAOsmReferencedAttr use case. This use case explains how to load an existing catalog containing StartUps, how to create a document to contain new features, how to retrieve StartUps and create new features by instantiating them, how to add features as referenced attributes of other features and how to save the new document. |
This use case is intended to help you understand the basics of working with referenced attributes. Its main intent is to explain the nature of referenced attributes, how to create them and how to assign them to features. Through this use case, you will also learn some important aspects recommended when programming with features. 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 and how it is created [1].
[Top]
CAAOsmReferencedAttr is a use case of the CAAObjectSpecsModeler.edu framework that illustrates ObjectSpecsModeler framework capabilities.
[Top]
The goal of CAAOsmReferencedAttr is to illustrate adding features to features as tk_specobject attributes. These features are then said to be "referenced". This use case uses the catalog defined in the CAAOsmCatalogSU use case [2] which contains StartUps based on the "book" example.
In this use case, a new feature, "CAAOsmPublisher1" is instantiated from the "CAAOsmPublisher" StartUp and its attributes are valuated."CAAOsmPublisher1" is added as a tk_specobject type of attribute to other features, "CAAOsmNovel1" and "CAAOsmNovel2". In other words, we see that two different novels have the same publisher.
To enrich the example, a new feature, "CAAOsmPublisher2" is created by instantiating the "CAAOsmPublisher" StartUp once more. Its attributes are valuated and it is added as a tk_specobject to another new feature, "CAAOsmDictionary1": "CAAOsmDictionary1" is not published by the same publishing house as are "CAAOsmNovel1" and "CAAOsmNovel2". Here is a relational schematic view of the operations performed in this use case:
Next, this article demonstrates that the notion of "parent" for a referenced feature has no meaning. If a "parent" feature is deleted, as is "CAAOsmDictionary1", the referenced feature remains intact and it can continue to be assigned to any number of other features. Note that this behavior is not true for "aggregated" features.
[Top]
To launch CAAOsmReferencedAttr , you will need to set up the build time environment, then compile CAAOsmReferencedAttr along with its prerequisites, set up the run time environment, and then execute the sample.
mkrun -c "CAAOsmReferencedAttr 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]
CAAOsmAggregatedAttr code is located in the CAAOsmReferencedAttr.m use case module of the CAAObjectSpecsModeler.edu framework:
Windows | InstallRootDirectory\CAAObjectSpecsModeler.edu\CAAOsmReferencedAttr.m |
Unix | InstallRootDirectory/CAAObjectSpecsModeler.edu/CAAOsmReferencedAttr.m |
where InstallRootDirectory
is the root directory of your CAA V5
installation. It is made of a unique source file named CAAOsmReferencedAttr.cpp.
[Top]
There are ten logical steps in CAAOsmReferencedAttr:
We will now comment each of these sections by looking at the code.
[Top]
See the referenced article [4<]/a> 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]
CATBaseUnknown *pPublisherSU = NULL; CATUnicodeString publisherSUType("CAAOsmPublisher"); rc = piCatalogOnContainer -> RetrieveSU(&pPublisherSU, &publisherSUType, "CATISpecObject"); if (NULL != pPublisherSU) cout << "CAAOsmPublisher StartUp retrieved OK" << endl << flush; else { (Process ERROR: Release pointers and return.) } // Get a CATISpecObject handle on the CAAOsmPublisher StartUp CATISpecObject *piPublisherSU = (CATISpecObject*) pPublisherSU; |
A StartUp is retrieved from the catalog using the CATICatalog::RetrieveSU
method. This method returns a CATBaseUnknown pointer in pPublisherSU
which is directly cast into a CATISpecObject pointer (piPublisherSU
).
The CATBaseUnknown pPublisherSU
pointer must be released
when no longer needed.
CATISpecAttrAccess *piSpecAttrAccessOnPubSU = NULL; rc = piPublisherSU -> QueryInterface(IID_CATISpecAttrAccess, void**) &piSpecAttrAccessOnPubSU); if (FAILED(rc)) { (Process ERROR: Release pointers and return.) } |
Once the StartUp has been retrieved, it is a good idea to immediately get the attribute keys that will be needed later on. These attribute keys remain globally available once they have been accessed. This means that valuating the attributes of any number instances of this StartUp will be more direct since there will be no need to access the attribute before valuating it. In order to get the StartUp's attribute keys, we first get a CATISpecAttrAccess handle on the StartUp.
ATISpecAttrKey *piKeyPublisherName = piSpecAttrAccessOnPubSU -> GetAttrKey("PublisherName"); if (NULL == piKeyPublisherName) { (Process ERROR: Release pointers and return.) } CATISpecAttrKey *piKeyPublisherAddress = piSpecAttrAccessOnPubSU -> GetAttrKey("PublisherAddress"); if (NULL == piKeyPublisherAddress) { (Process ERROR: Release pointers and return.) } piSpecAttrAccessOnPubSU -> Release(); |
Using the CATISpecAttrAccess::GetAttrKey
, we get a CATISpecAttrKey
handle to each attribute that will be valuated.
CATUnicodeString publisher1("CAAOsmPublisher1"); CATISpecObject *piPubInst1 = piPublisherSU -> Instanciate(publisher1, piRootContainer); if (NULL != piPubInst1) cout << "CAAOsmPublisher SU instance 1 created OK" << endl << flush; else { (Process ERROR: Release pointers and return.) } |
Finally, a new feature, "CAAOsmPublisher1" is created in the root container by instantiating the StartUp "CAAOsmPublisher".
CATISpecAttrAccess *piSpecAttrAccessOnPub1 = NULL; rc = piPubInst1 -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnPub1); if (FAILED(rc)) { (Process ERROR: Release pointers and return.) } piSpecAttrAccessOnPub1 -> SetString(piKeyPublisherName, "Collins Press"); piSpecAttrAccessOnPub1 -> SetString(piKeyPublisherAddress, "London"); piSpecAttrAccessOnPub1 -> Release(); |
The new feature's attributes are valuated using a CATISpecAttrAccess
handle and SetString
.
[Top]
Now that "CAAOsmPublisher1" has been created, it will be assigned as a referenced attribute to a new feature, "CAAOsmNovel1". So, let's create "CAAOsmNovel1".
CATBaseUnknown *pNovelSU = NULL; CATUnicodeString novelSUType("CAAOsmNovel"); rc = piCatalogOnContainer -> RetrieveSU(&pNovelSU, &novelSUType, "CATISpecObject"); if (pNovelSU) cout << "CAAOsmNovel StartUp retrieved OK" << endl << flush; else { (Process ERROR: Release pointers and return.) } // Get a CATISpecObject handle on the CAAOsmNovel StartUp CATISpecObject *piNovelSU = (CATISpecObject*) pNovelSU; |
The "CAAOsmNovel" StartUp is retrieved using the RetrieveSU
method of CATICatalog.
CATISpecAttrAccess *piSpecAttrAccessOnNovel = NULL; rc = piNovelSU -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnNovel); if (FAILED(rc)) { (Process ERROR: Release pointers and return.) } CATISpecAttrKey *piKeyNovelPublisher = piSpecAttrAccessOnNovel -> GetAttrKey("BookPublisher"); if (NULL == piKeyNovelPublisher) { (Process ERROR: Release pointers and return.) } |
We get a CATISpecAttrAccess handle in order to get the attribute
keys from the StartUp using GetAttrKey
.
CATUnicodeString novel1("CAAOsmNovel1"); CATISpecObject *piNovelInst1 = piNovelSU -> Instanciate(novel1, piRootContainer); if (piNovelInst1) cout << "CAAOsmNovel SU instance 1 created OK" << endl << flush; else { (Process ERROR: Release pointers and return.) } |
And now, we can instantiate the StartUp and create a new feature "CAAOsmNovel1":
[Top]
CATISpecAttrAccess *piSpecAttrAccessOnNov1 = NULL; rc = piNovelInst1 -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnNov1); piNovelInst1 -> Release(); if (FAILED(rc)) { (Process ERROR: Release pointers and return.) } piSpecAttrAccessOnNov1 -> SetSpecObject(piKeyNovelPublisher, piPubInst1); piSpecAttrAccessOnNov1 -> Release(); |
The attribute "BookPublisher" of the StartUp
"CAAOsmNovel" has been defined as a tk_specobject. This
means that this attribute must be valuated by a feature object. We assign
the feature "CAAOsmPublisher1" as a referenced attribute (of tk_specobject
type) of "CAAOsmNovel1". This is done using the SetSpecObject
method of CATISpecAttrAccess to which we pass the attribute key and
the CATISpecObject handle to the feature
"CAAOsmPublisher1".
CATUnicodeString novel2("CAAOsmNovel2"); CATISpecObject *piNovelInst2 = piNovelSU -> Instanciate(novel2, piRootContainer); pNovelSU -> Release(); if (piNovelInst2) cout << "CAAOsmNovel SU instance 2 created OK" << endl << flush; else { (Process ERROR: Release pointers and return.) } // Valuate attribute "BookPublisher" for "CAAOsmNovel2" with the new instance of // "CAAOsmPublisher" ("CAAOsmPublisher1") CATISpecAttrAccess *piSpecAttrAccessOnNov2 = NULL; rc = piNovelInst2 -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnNov2); if (FAILED(rc)) { (Process ERROR: Release pointers and return.) } piSpecAttrAccessOnNov2 -> SetSpecObject(piKeyNovelPublisher, piPubInst1); piKeyNovelPublisher -> Release(); piNovelInst2 -> Release(); piSpecAttrAccessOnNov2 -> Release(); piPubInst1 -> Release(); |
Since "NovelPublisher" is of type tk_specobject, this means that the feature assigned to "CAAOsmNovel1" as a referenced attribute can be assigned to other features as well. To show this, we create a new feature, "CAAOsmNovel2" and assign "CAAOsmPublisher1" to it.
As you can see, the novels "CAAOsmNovel1" and "CAAOsmNovel2" both have the same publisher.
[Top]
CATUnicodeString publisher2("CAAOsmPublisher2"); CATISpecObject *piPubInst2 = piPublisherSU -> Instanciate(publisher2, piRootContainer); pPublisherSU -> Release(); if (piPubInst2) cout << "CAAOsmPublisher SU instance 2 created OK" << endl << flush; else { (Process ERROR: Release pointers and return.) } CATISpecAttrAccess *piSpecAttrAccessOnPub2 = NULL; rc = piPubInst2 -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnPub2); if (FAILED(rc)) { (Process ERROR: Release pointers and return.) } piSpecAttrAccessOnPub2 -> SetString(piKeyPublisherName, "Larousse"); piSpecAttrAccessOnPub2 -> SetString(piKeyPublisherAddress, "Paris"); piKeyPublisherName -> Release(); piKeyPublisherAddress -> Release(); piSpecAttrAccessOnPub2 -> Release(); |
Now, to further our example, we create a new feature, "CAAOsmPublisher2" from the "CAAOsmPublisher" StartUp and we valuate its attributes with the names and address of another publishing house.
[Top]
CATBaseUnknown *pDictionarySU = NULL; CATUnicodeString dictionarySUType("CAAOsmDictionary"); rc = piCatalogOnContainer -> RetrieveSU(&pDictionarySU, &dictionarySUType, "CATISpecObject"); if (pDictionarySU) cout << "CAAOsmDictionary StartUp retrieved OK" << endl << flush; else { (Process ERROR: Release pointers and return.) } // Get a CATISpecObject handle on the CAAOsmDictionary StartUp CATISpecObject *piDictionarySU = (CATISpecObject*) pDictionarySU; // Get the dictionary's attribute key "BookPublisher" CATISpecAttrAccess *piSpecAttrAccessOnDict = NULL; rc = piDictionarySU -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnDict); if (FAILED(rc)) { (Process ERROR: Release pointers and return.) } CATISpecAttrKey *piKeyDictPublisher = piSpecAttrAccessOnDict -> GetAttrKey("BookPublisher"); if (NULL == piKeyDictPublisher) { (Process ERROR: Release pointers and return.) } piSpecAttrAccessOnDict -> Release(); // Get an instance of the CAAOsmDictionary StartUp CATUnicodeString dictionary1("CAAOsmDictionary1"); CATISpecObject *piDictInst1 = piDictionarySU -> Instanciate(dictionary1, piRootContainer); if (piDictInst1) cout << "CAAOsmDictionary SU instance 1 created OK" << endl << flush; else { (Process ERROR: Release pointers and return.) } |
We also create a new feature, "CAAOsmDictionary1" from the "CAAOsmDictionary" StartUp and we acquire the attribute keys.
[Top]
CATISpecAttrAccess *piSpecAttrAccessOnDict1 = NULL; rc = piDictInst1 -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnDict1); if (FAILED(rc)) { (Process ERROR: Release pointers and return.) } piSpecAttrAccessOnDict1 -> SetSpecObject(piKeyDictPublisher, piPubInst2); piSpecAttrAccessOnDict1 -> Release(); |
Now, we assign "CAAOsmPublisher2" to "CAAOsmDictionary1" as a referenced feature in order to show that different types of "CAAOsmBooks", such as dictionaries and novels, can have different publishers.
[Top]
CATISpecObject *piPubInst2Father = piPubInst2 -> GetFather(); if (NULL == piPubInst2Father) cout << "OK: Feature CAAOsmPublisher2 does not have a father!" << endl << flush; else { cout << "ERROR: Feature CAAOsmPublisher2 should not have a father and it does!" << endl << flush; piPubInst2Father -> Release(); } |
A feature used as a referenced attribute does not have a
"parent": it exists independently of any other feature. Therefore,
the method GetFather
has no meaning when applied to a
referenced feature: it returns a NULL.
LifeCycleObject *pDict = NULL; rc = piDictInst1 -> QueryInterface(IID_LifeCycleObject, (void**) &pDict); if (FAILED(rc)) { (Process ERROR: Release pointers and return.) } else pDict -> remove(); pDict -> Release(); piDictInst1 -> Release(); |
If "CAAOsmDictionary1" is deleted, "CAAOsmPublisher2"
can still be assigned to other features as a referenced attribute. So, let's
delete "CAAOsmDictionary1" and see. This is done using a LifeCycleObject
handle that we acquire on the "CAAOsmDictionary1" feature. Using
this handle, we perform a remove
in order to delete the
feature.
CATUnicodeString dictionary2("CAAOsmDictionary2"); CATISpecObject *piDictInst2 = piDictionarySU -> Instanciate(dictionary2, piRootContainer); pDictionarySU -> Release(); if (piDictInst2) cout << "CAAOsmDictionary SU instance 2 created OK" << endl << flush; else { (Process ERROR: Release pointers and return.) } |
To show that "CAAOsmPublisher2" is not also deleted along with "CAAOsmDictionary1", assign it to a new instance of "CAAOsmDictionary". In order to do this, first we must create a new instance of "CAAOsmDictionary" that we will call "CAAOsmDictionary2".
CATISpecAttrAccess *piSpecAttrAccessOnDict2 = NULL; rc = piDictInst2 -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnDict2); piDictInst2 -> Release(); if (FAILED(rc)) { (Process ERROR: Release pointers and return.) } piSpecAttrAccessOnDict2 -> SetSpecObject(piKeyDictPublisher, piPubInst2); piKeyDictPublisher -> Release(); piSpecAttrAccessOnDict2 -> Release(); piPubInst2 -> Release(); |
And now, we can assign "CAAOsmPublisher2" to the new
"CAAOsmDictionary2" feature using SetSpecObject
.
[Top]
Before proceeding to save the document, be sure to release any remaining pointers that will no longer be used:
piRootContainer -> Release(); piCatalogOnContainer -> 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 to use referenced attributes. Specifically, it has illustrated:
AccessCatalog
global functionRetrieveSU
method of CATICatalogGetAttrKey
method of CATISpecAttrAccessInstanciate
method of CATISpecObjectSet
..."
methods of CATISpecAttrAccesstk_specobject
-type
attribute using the SetSpecObject
method of CATISpecAttrAccessremove
method of LifeCycleObject.[Top]
[1] | Feature Modeler Conceptual 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.