3D PLM PPR Hub Open Gateway

Feature Modeler

Aggregating Features to Features

Working with aggregated features
Use Case

Abstract

This article discusses the CAAOsmAggregatedAttr use case. This use case aims to explain how to create and assign aggregated attributes to features and the concepts related to them.


What You Will Learn With This Use Case

This use case is intended to help you understand the basics of working with aggregated attributes. Its main intent is to explain the nature of aggregated 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]

The CAAOsmAggregatedAttri Use Case

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

[Top]

What Does CAAOsmAggregatedAttr Do

The goal of the CAAOsmAggregatedAttr use case is to illustrate adding features to features as tk_component attributes. These features are said to be "aggregated".

Several chapters for a given novel, The Three Musketeers, are described here. This use case uses the catalog defined in the CAAOsmCatalogSU use case [2] which contains StartUps from the "Book" example. We want to assign titles to the chapters and describe their length by giving the first and last page numbers they cover. The "CAAOsmChapter" StartUp is retrieved from the catalog. Its attributes are "ChapterTitle", "FirstPage" and "LastPage". Three "CAAOsmChapter" instances of the StartUp are created. Their attributes are valuated and each feature is assigned to the novel as an item in a list (list of chapters). The "CAAOsmChapter" feature has been defined as an aggregated feature in order to limit its existence to only one novel: a chapter is unique, it cannot exist in more than one novel.

Working with lists is also illustrated here by scanning through the chapter titles of "CAAOsmNovel1".

[Top]

How to Launch CAAOsmAggregatedAttr

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

mkrun -c "CAAOsmAggregatedAttr 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 CAAOsmAggregatedAttr Code

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

Windows InstallRootDirectory\CAAObjectSpecsModeler.edu\CACAAOsmAggregatedAttr.m
Unix InstallRootDirectory/CAAObjectSpecsModeler.edu/CAAOsmAggregatedAttr.m

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

[Top]

Step-by-Step

There are eight logical steps in the CAAOsmAggregatedAttr:

  1. Prolog
  2. Loading the Catalog
  3. Creating Three Features from the "CAAOsmChapter" StartUp
  4. Creating the Feature "CAAOsmNovel1"
  5. Assigning "CAAOsmChapter" Features as Aggregated Attributes of "CAAOsmNovel1"
  6. Scanning Through the List of "NovelChapter" Titles
  7. Illustrating the Notion of an "Aggregated" Feature
  8. Epilog

We will now comment each of these 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 Three Features from the "CAAOsmChapter" StartUp

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

    A StartUp is retrieved from the catalog using the CATICatalog::RetrieveSU method. This method returns a CATBaseUnknown pointer in pChapterSU which is directly cast into a CATISpecObject pointer (piChapterSU). The CATBaseUnknown pChapterSU pointer must be released when no longer needed.

  2. Get attribute keys
    CATISpecAttrAccess *piSpecAttrAccessOnChapt = NULL;
    rc = piChapterSU -> QueryInterface(IID_CATISpecAttrAccess,
                                       (void**) &piSpecAttrAccessOnChapt);
    if (FAILED(rc)) 
    {
       (Process ERROR:  Release pointers and return.)
    }
    
    CATISpecAttrKey *piKeyChapterTitle = piSpecAttrAccessOnChapt ->
    		GetAttrKey("ChapterTitle");
    if (NULL == piKeyChapterTitle) 
    {
       (Process ERROR:  Release pointers and return.)
    }
    
    CATISpecAttrKey *piKeyFirstPage = piSpecAttrAccessOnChapt ->
    		GetAttrKey("FirstPage");
    if (NULL == piKeyFirstPage) 
    {
       (Process ERROR:  Release pointers and return.)
    }
    
    CATISpecAttrKey *piKeyLastPage = piSpecAttrAccessOnChapt -> 
    		GetAttrKey("LastPage");
    if (NULL == piKeyLastPage) 
    {
       (Process ERROR:  Release pointers and return.)
    }
    
    piSpecAttrAccessOnChapt -> Release();

    Once we have a pointer to the StartUp, the first thing to do is to get the attribute keys that will be needed later on in order to valuate the attributes. Using the CATISpecObject handle, we get a CATISpecAttrAccess handle with which we execute the GetAttrKey method in order to get the attribute keys.

  3. Instantiate "CAAOsmChapter" StartUp
    CATUnicodeString chapter1("CAAOsmChapter1");
    CATISpecObject *piChaptInst1 = piChapterSU ->
    		Instanciate(chapter1,
    		            piRootContainer);
    if (NULL != piChaptInst1) cout << "CAAOsmChapter SU instance 1 created OK" << endl << flush;
    else
    {
       (Process ERROR:  Release pointers and return.)
    }

    Now we are finally ready to create a first feature object by instantiating the StartUp "CAAOsmChapter". This is done using the Instanciate method of CATISpecObject.

  4. Valuate "CAAOsmChapter1" attributes
    CATISpecAttrAccess *piSpecAttrAccessOnChapt1 = NULL;
    rc = piChaptInst1 -> QueryInterface(IID_CATISpecAttrAccess,
                                        (void**) &piSpecAttrAccessOnChapt1);
    if (FAILED(rc)) 
    {
       (Process ERROR:  Release pointers and return.)
    }
    
    piSpecAttrAccessOnChapt1 -> SetString(piKeyChapterTitle,
                                          "The Three Presents of M.D Artagnan, the Father");
    piSpecAttrAccessOnChapt1 -> SetInteger(piKeyFirstPage,
                                           11);
    piSpecAttrAccessOnChapt1 -> SetInteger(piKeyLastPage,
                                           27);
    piSpecAttrAccessOnChapt1 -> Release();

    Once the feature has been created, its attributes can be valuated using the Set... methods of CATISpecAttrAccess. So first of all, let's get a CATISpecAttrAccess handle on the new feature "CAAOsmChapter1" and then valuate the attributes.

    The same procedure for creating and valuating attributes is performed on two more "CAAOsmChapter" features: "CAAOsmChapter2" and "CAAOsmChapter3".

[Top]

Creating the Feature "CAAOsmNovel1"

The three "CAAOsmChapter" features previously created will be added as a list to the feature "CAAOsmNovel1" which must first be created based on the StartUp "CAAOsmNovel".

CATBaseUnknown *pNovelSU = NULL;
CATUnicodeString novelSUType("CAAOsmNovel");
rc = piCatalogOnContainer -> RetrieveSU(&pNovelSU,
                                        &novelSUType,
	                               "CATISpecObject");
if (NULL != 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;
// Retrieve the CAAOsmNovel's attribute key "NovelChapter"

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

CATISpecAttrKey *piKeyNovelChapter = piSpecAttrAccessOnNovel ->
		GetAttrKey("NovelChapter");
if (NULL == piKeyNovelChapter) 
{
   (Process ERROR:  Release pointers and return.)
}

piSpecAttrAccessOnNovel -> Release();

// Get an instance of the CAAOsmNovel StartUp

CATUnicodeString novel1("CAAOsmNovel1");
CATISpecObject *piNovelInst1 = piNovelSU -> 
		Instanciate(novel1,
		            piRootContainer);
pNovelSU -> Release();
if (NULL != piNovelInst1) cout << "CAAOsmNovel SU instance 1 created OK" << endl << flush;
else 
{
   (Process ERROR:  Release pointers and return.)
}

We proceed, therefore, as we have before, by retrieving the StartUp and its attribute keys and then instantiating it.

[Top]

Assigning "CAAOsmChapter" Features as Aggregated Attributes of "CAAOsmNovel1"

Now, the "CAAOsmChapter" features can be assigned to "CAAOsmNovel1" as a list of objects of the attribute "NovelChapter" defined in the StartUp as a tk_list of tk_components. This means that the attribute "NovelChapter" will be assigned a list of features and that these features will be tied to the "CAAOsmNovel1" feature as its children The "CAAOsmChapter" features will no longer exist independently of "CAAOsmNovel1": if this "parent" feature is ever deleted, so are the "children" features. Moreover, the "CAAOsmChapter" features cannot be aggregated to any other "parent" feature.

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

piSpecAttrAccessOnNov1 -> SetSpecObject(piKeyNovelChapter,
                                        piChaptInst1);
piSpecAttrAccessOnNov1 -> SetSpecObject(piKeyNovelChapter,
                                        piChaptInst2);
piSpecAttrAccessOnNov1 -> SetSpecObject(piKeyNovelChapter,
                                        piChaptInst3);
piChaptInst2 -> Release();
piChaptInst3 -> Release();

Using a CATISpecAttrAccess pointer based on "CAAOsmNovel1", the list of "NovelChapter" is valuated using SetSpecObject to which we pass a handle to the attribute key of the novel chapter that we retrieved on the "CAAOsmNovel" StartUp and the CATISpecObject handle to the feature instance of the different chapters to be aggregated by "CAAOsmNovel1".

Note that piChaptInst1 is not yet released because it will be used later.

[Top]

Scanning Through the List of "NovelChapter" Titles

int ListSize = piSpecAttrAccessOnNov1 -> GetListSize(piKeyNovelChapter);
cout << "The Novel chapter titles (" << ListSize <<") are: " << endl;
for ( int i=1 ; i <= ListSize ; i++ )
{
   CATISpecObject *piNovelChapter = piSpecAttrAccessOnNov1 -> GetSpecObject(piKeyNovelChapter,i);
   ...

   CATISpecAttrAccess *piSpecAttrAccessOnNovChapt = NULL;
   rc = piNovelChapter -> QueryInterface(IID_CATISpecAttrAccess, (void**) &piSpecAttrAccessOnNovChapt);
   piNovelChapter -> Release(); 
   piNovelChapter = NULL ;

   ...
   cout << piSpecAttrAccessOnNovChapt -> GetString(piKeyChapterTitle).CastToCharPtr() << endl;

   iSpecAttrAccessOnNovChapt -> Release(); piSpecAttrAccessOnNovChapt = NULL ;
}

piSpecAttrAccessOnNov1 -> Release(); piSpecAttrAccessOnNov1 = NULL ;
piKeyChapterTitle -> Release(); piKeyChapterTitle = NULL ;
piKeyNovelChapter -> Release(); piKeyNovelChapter = NULL ;

In order to scan through a list of feature attributes, we use GetListSize to retrieve the size of the list. Within the loop, GetSpecObject the ieme feature attribute and GetString (or GetInteger, etc.) returns the value of the attribute itself.

[Top]

Illustrating the Notion of an "Aggregated" Feature

CATISpecObject *piChaptInst1Father = piChaptInst1 -> GetFather();
if (NULL != piChaptInst1Father)
{
   cout << "The 'ChapterInst1' parent feature is " << endl;
   cout << piChaptInst1Father -> GetName().ConvertToChar() << endl;
}
piChaptInst1Father -> Release();

piChaptInst1 -> Release();

The "parent" of any given instance of "CAAOsmChapter" that has been aggregated to "CAAOsmNovel1" is "CAAOsmNovel1". We use the GetFather method of CATISpecObject to retrieve a handle to the parent of a given "CAAOsmChapter" instance. Then, we use the GetName method of CATISpecObject to retrieve its name. Therefore, the trace comes out to be:

The 'ChapterInst1' parent feature is CAAOsmNovel1

[Top]

Epilog

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]


In Short

This use case has demonstrated how to use aggregated attributes. Specifically, it has illustrated:

[Top]


References

[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]

History

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

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