3D PLM PPR Hub Open Gateway

Feature Modeler

Working with Cut, Copy and Paste Operations

Performing CCP operations on features
Use Case

Abstract

This article discusses the CAAOsmCCP use case. This use case explains how to perform Cut, Copy and Paste operations on feature objects in applicative containers.


What You Will Learn With This Use Case

This use case is intended to help you understand how to perform Cut, Copy and Paste operations on feature objects in applicative containers. Specifically, you will learn how to:

Before getting to the use case itself, you should have a good understanding of what a feature object is and how it is created [1].

[Top]

The CAAOsmCCP Use Case

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

[Top]

What Does CAAOsmCCP Do

The goal of CAAOsmCCP is to illustrate performing CCP operations on feature objects in both batch and interactive modes. To exemplify this, it uses the "CAAOsmNovel" and "CAAOsmChapter" StartUps defined in the catalog created by the CAAOsmCatalogSU use case [2]. These StartUps are instantiated in an applicative container created in a new document. Here is an image of the initial contents of this document:
Fig.1: Initial CATPart Document Contents

Note that two CATFeatCont containers have been created, one of which contains one instance of the "CAAOsmNovel" StartUp and three new instances of the "CAAOsmChapter" StartUp. The second CATFeatCont is initially empty.

Next, "CAAOsmChapter1" and "CAAOsmChapter2" are copied from the first container, said to be the source container, to the second, said to be the target container. "CAAOsmChapter1" is removed from the source container. This illustrates a Cut/Paste of "CAAOsmChapter1" as it is removed from the source container and pasted in the target container and a Copy/Paste of "CAAOsmChapter2" from the source container to the target container. This example is meant to show how you would program this operation in batch mode, without needing to pass through the clipboard. Here is an image of the CATPart Document after this operation has been performed:
Fig.2 CATPart Document Contents After the First CCP Operation

Finally, "CAAOsmChapter3" is copied from the source container to the target container. This operation is shown as it would need to be programmed in interactive mode. In this case, it is first necessary to extract the object from the source container and store it in the clipboard. Then, it is extracted from the clipboard and pasted in the target container. Here is an image of the CATPart Document after this second operation has been performed:

Fig.3 CATPart Document Contents After the Second CCP Operation

[Top]

How to Launch CAAOsmCCP

To launch CAAOsmCCP, you will need to set up the build time environment, then compile CAAOsmCCP along with its prerequisites, set up the run time environment, and then execute the sample as follows:

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

This step is fully described in the referenced article [3]. Following are the arguments passed when launching the use case:

[Top]

Where to Find the CAAOsmCCP Code

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

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

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

[Top]

Step-by-Step

There are eight logical steps in CAAOsmCCP:

  1. Creating a New Document
  2. Initializing Formats for CCP Operations
  3. Creating Applicative Source and Target Containers
  4. Loading an Existing Catalog
  5. Instantiating New Feature Objects from Existing StartUps
  6. Case 1: CCP in Batch Mode
  7. Case 2: CCP in Interactive Mode
  8. Epilog

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

[Top]

Creating a New Document

...
// We will work with a "CATPart" document. 

CATDocument *pDoc = NULL;
rc = CATDocumentServices::New("Part",
                              pDoc);
if (NULL != pDoc) cout << "New document created OK" << endl << flush;
else
{
   cout << "ERROR in creating New document" << endl << flush;
   return 2;
}
...

A new document is created simply by executing the New method of CATDocumentServices.

CATLockDocument(*pDoc);

In general, when working in batch with CCP operations, it is a good idea to lock the document ahead of time in order to avoid problems when wanting to save it or remove it from the session. This is done using the CATLockDocument method of CATSessionServices. Remember, however, that it is extremely important not to forget to unlock the document at the end!

// Retrieve the root container of the document
CATInit *piInitOnDoc = NULL;
rc = pDoc -> QueryInterface(IID_CATInit,
                            (void**) &piInitOnDoc);
if (FAILED(rc)) 
{
   cout << "ERROR in QueryInterface on CATInit for doc" << endl << flush;
   return 3;
}

const CATIdent idCATIContainer = "CATIContainer";
CATIContainer *piRootContainer = NULL;
piRootContainer = (CATIContainer*) piInitOnDoc -> GetRootContainer(idCATIContainer);

piInitOnDoc -> Release();
piInitOnDoc = NULL;

if (NULL == piRootContainer)
{
   cout << "ERROR in GetRootContainer" << endl << flush;
   return 4;
}

It is also necessary to retrieve the root container of the newly-created document because it will be needed in order to load the catalog of StartUps. The root container is retrieved using the GetRootContainer method of CATInit.

[Top]

Initializing Formats for CCP Operations

IdFormat FEATURE_FORMAT = "CATFeatCont";
const CATFormat *featFormat = ::SpecBindNativeFormat(FEATURE_FORMAT);

Formats are used by the CCP system in order to perform specific user-defined actions. A format type can be any user-defined string. Format types must be defined in the CCP system before they can be used. Use SpecBindNativeFormat to declare them. If no formats are needed, as in this use case, the container's late type is used by default. Here we are working in a "CATFeatCont" container.

[Top]

Creating Applicative Source and Target Containers

CATIdent idAppliCont = "CATFeatCont";
CATUnicodeString sourceAppliContId ("CAAOsmSourceContainer");
CATBaseUnknown *pSourceContainer = NULL;
rc = ::CATCreateApplicativeContainer(&pSourceContainer,        // appli cont created
                                     pDoc,                     // document  
                                     idAppliCont,              // type of appli cont
                                     IID_CATIContainer,        // interface type of appli cont
                                     "",                       // supertype of appli cont 
                                     sourceAppliContId);       // name of appli cont
if (SUCCEEDED(rc)) cout << "Source applicative container created OK" << endl << flush;
else
{
   cout << "ERROR in creating source applicative container" << endl << flush;
   piRootContainer -> Release();
   return 5;
}

A new applicative container is created using the CATCreateApplicativeContainer global function. See the CAAOsmAppliCont [5] use case for a more detailed description of this service. Above you can see how to create the first or "Source" container. The same procedure is performed for the second or "Target" container.

[Top]

Loading an Existing Catalog

Loading a catalog means opening the catalog document in order to allow the access to the StartUps it contains.

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

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

[Top]

Instantiating New Feature Objects from Existing StartUps

  1. Retrieving StartUps
    CATBaseUnknown *pNovelSU = NULL;
    CATUnicodeString novelSUType("CAAOsmNovel");
    rc = piCatalog -> RetrieveSU(&pNovelSU, 
                                 &novelSUType,
    	                     "CATISpecObject");
    	
    if (NULL != pNovelSU) cout << "CAAOsmNovel StartUp retrieved OK" << endl << flush;
    else
    {
       cout << "ERROR in retrieving CAAOsmNovel StartUp" << endl << flush;
       pSourceContainer -> Release();
       pTargetContainer -> Release();
       piCatalog -> Release();
       return 7;
    }
    
    // Get a CATISpecObject handle on the CAAOsmNovel StartUp
    
    CATISpecObject *piNovelSU = (CATISpecObject*) pNovelSU;

    In order to create new feature objects in the document, it is first necessary to retrieve an existing StartUp. The example above shows how the StartUp whose type is "CAAOsmNovel" is retrieved from the catalog. The same must be done for the "CAAOsmChapter" StartUp whose type is "CAAOsmChapter".

  2. Instantiating StartUps to create new feature objects
    CATISpecObject *piNovelInst1 = piNovelSU -> 
    	Instanciate(CATUnicodeString("CAAOsmNovel1"),
                        pSourceContainer);
    pNovelSU -> Release();
    pNovelSU = NULL;
    
    if (NULL != piNovelInst1) cout << "CAAOsmNovel instance 1 created OK" << endl << flush;
    else 
    {
       cout << "ERROR in creating instance 1 of CAAOsmNovel SU" << endl << flush;
       pSourceContainer -> Release();
       pTargetContainer -> Release();
       piCatalog -> Release();
       return 8;
    }
    piNovelInst1 -> Release();
    piNovelInst1 = NULL;

    A new feature object is created in the source container by instantiating a StartUp. Above, you can see that a new feature object "CAAOsmNovel1" is created using the Instanciate method of CATISpecObject. The same must be done in order to create the other three features, "CAAOsmChapter1", "CAAOsmChapter2" and "CAAOsmChapter3" which will be needed in this use case. They will be handled using piChapterInst1, piChapterInst2 and piChapterInst3 respectively.

[Top]

Case 1: CCP in Batch Mode

This first case deals with performing CCP operations while working in batch mode. This case is simpler, since there is no need to pass through the clipboard, the CCP operations are performed directly. However for a Mechanical feature, the second methodology must be used. See CCP in Interactive Mode.

The first case directly pastes "CAAOsmChapter1" and "CAAOsmChapter2" into the target container and then deletes "CAAOsmChapter1" from the source container.

  1. Get a CATICutAndPastable handle on the target container
    CATICutAndPastable *piCutAndPastableOnTargetCont = NULL;
    rc = pTargetContainer -> QueryInterface(IID_CATICutAndPastable,
                                            (void**) &piCutAndPastableOnTargetCont);
    pTargetContainer -> Release();
    pTargetContainer = NULL;
    if (FAILED(rc)) 
    {
       cout << "ERROR in QueryInterface on CATICutAndPastable on Target Container" << endl << flush;
       pSourceContainer -> Release();
       piChapterInst1 -> Release();
       piChapterInst2 -> Release();
       piChapterInst3 -> Release();
       return 3;
    }
  2. Copy objects from the source container to the target container
    ListOfVarBaseUnknown listToPaste;
    listToPaste.Append(piChapterInst1);
    listToPaste.Append(piChapterInst2);
    
    ListOfVarBaseUnknown listPastedObjects = piCutAndPastableOnTargetCont -> Paste (listToPaste,
                                                                                    NULL,
                                                                                    NULL);
    if (listPastedObjects.Size() != 2)
    {
       cout << "ERROR in Paste of objects" << endl << flush;
       pSourceContainer -> Release();
       piChapterInst1 -> Release();
       piChapterInst2 -> Release();
       piChapterInst3 -> Release();
       return 9;
    }
    else cout << "Objects Pasted in Target Container from Source Container OK" << endl << flush;
    	
    piChapterInst2 -> Release();
    piChapterInst2 = NULL;

    A copy in batch mode is simply performed by pasting objects directly in the target container. This is done using the Paste method of CATICutAndPastable which takes the following arguments:

  3. Get a CATICutAndPastable handle on the source container
    CATICutAndPastable *piCutAndPastableOnSourceCont = NULL;
    rc = pSourceContainer -> QueryInterface(IID_CATICutAndPastable,
                                            (void**) &piCutAndPastableOnSourceCont);
    pSourceContainer -> Release();
    pSourceContainer = NULL;
    if (FAILED(rc)) 
    {
       cout << "ERROR in QueryInterface on CATICutAndPastable on Source Container" << endl << flush;
       piChapterInst1 -> Release();
       piChapterInst3 -> Release();
       piCutAndPastableOnTargetCont -> Release();
       return 3;
    }
  4. Deleting objects from the source container
    ListOfVarBaseUnknown listToRemove;
    listToRemove.Append(piChapterInst1);
    
    piChapterInst1 -> Release();
    piChapterInst1 = NULL;
     
    if (piCutAndPastableOnSourceCont -> Remove (listToRemove, NULL))
       cout << "Remove of objects from Source Container succeeded" << endl << flush;
    else 
    {
       cout << "Remove failed" << endl << flush;
       piCutAndPastableOnSourceCont -> Release();
       piCutAndPastableOnTargetCont -> Release();
       piChapterInst3 -> Release();
       return 10;
    }  

    Deleting an object in batch mode is simply performed by passing the list of objects to be removed as input to the Remove method of CATICutAndPastable. Note that the second argument to this method is the format type which is not used here.

[Top]

Case 2: CCP in Interactive Mode

This second case deals with performing CCP operations while working in interactive mode. In this case, all operations need to pass through the clipboard. In other words, objects must first be extracted from the source container to the clipboard, from which they must again be extracted in order to be copied to the target container. In other words, "CAAOsmChapter3" will be extracted from the source container to the clipboard from which it will be extracted and pasted into the target container.

  1. Extract objects from the source container to the clipboard
    ListOfVarBaseUnknown newListToCopy;
    ListOfVarBaseUnknown listFromCopy;
    listFromCopy.Append(piChapterInst3);
    
    piChapterInst3 -> Release();
    piChapterInst3 = NULL;
    
    int result = NULL;
    result = piCutAndPastableOnSourceCont -> BoundaryExtract (newListToCopy, 
                                                              &listFromCopy,
                                                              NULL);
    if (NULL != result)
    {
       cout << "BoundaryExtract from Source Container succeeded" << endl << flush;
       cout << "Number of objects extracted = " << newListToCopy.Size() << endl << flush;
    }
    else
    {
       cout << "BoundaryExtract failed" << endl << flush;
       piCutAndPastableOnSourceCont -> Release();
       piCutAndPastableOnTargetCont -> Release();
       return 11;
    }
    
    VarBaseUnknown pExtractedList;
    pExtractedList = piCutAndPastableOnSourceCont -> Extract (newListToCopy,
                                                              NULL);
    piCutAndPastableOnSourceCont -> Release();
    piCutAndPastableOnSourceCont = NULL;

    In the above example, objects are first stored in a list using the BoundaryExtract method of CATICutAndPastable which is useful when constructing a list of objects. This method takes the following arguments:

    Next, using the Extract method of CATICutAndPastable, the objects contained in the list passed into the first argument are actually extracted and saved in the clipboard. The second argument to this method is again the iAnImposedFormat which is not used.

  2. Get a CATICutAndPastable handle on the clipboard container (pExtractedList)
    CATICutAndPastable *piCutAndPastableOnExtractedList = NULL;
    rc = pExtractedList -> QueryInterface(IID_CATICutAndPastable,
    		                      (void**) &piCutAndPastableOnExtractedList);
    if (FAILED(rc)) 
    {
       cout << "ERROR in QueryInterface on CATICutAndPastable on Target Container" << endl << flush;
       return 3;
    }

    In order to paste objects, they must be extracted from the clipboard. First of all, it is necessary to get a CATICutAndPastable handle on the container representing the clipboard. The pointer to this container was returned by the preceding Extract operation.

  3. Copy objects from the clipboard to the target container
    ListOfVarBaseUnknown extractedListToCopy;
        
    result = NULL;
    result = piCutAndPastableOnExtractedList -> BoundaryExtract (extractedListToCopy, 
                                                                 NULL,
                                                                 NULL);
    if (NULL != result)
    {
       cout << "BoundaryExtract from Clipboard succeeded" << endl << flush;
       cout << "Number of objects extracted = " << extractedListToCopy.Size() << endl << flush;
    }
    else
    {
       cout << "BoundaryExtract failed" << endl << flush;
       piCutAndPastableOnTargetCont -> Release();
       return 11;
    }
    
    piCutAndPastableOnExtractedList -> Release();
    piCutAndPastableOnExtractedList = NULL;
    
    listPastedObjects = piCutAndPastableOnTargetCont -> Paste (extractedListToCopy,
                                                               NULL,
                                                               NULL);
    if (listPastedObjects.Size() != 1)
    {
       cout << "ERROR in Paste of objects" << endl << flush;
       return 9;
    }
    else cout << "Objects Pasted from Clipboard to Target Container OK" << endl << flush;
    	
    piCutAndPastableOnTargetCont -> Release();
    piCutAndPastableOnTargetCont = NULL;

    Next, a BoundaryExtract is performed passing a NULL pointer in the second argument, thus creating a list of all of the objects currently waiting in the clipboard. Then, the Paste method simply copies the objects contained in this list into the target container.

[Top]

Epilog

See the referenced article [4] for a detailed description of the steps to go through when saving the document. Note, however, that an unlock of the document must be performed in order to effectively release it from the session:

CATUnLockDocument(*pDoc);

This is done using the CATUnlockDocument method of CATSessionServices.

Note that the catalog document does not need to be removed from the session.

[Top]


In Short

This use case has demonstrated how to perform Cut, Copy and Paste operations on feature objects in applicative containers in both batch and interactive mode. 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
[5] Creating Features in an Applicative Container
[Top]

History

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

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