ENOVIA V5 VPM

VPM Interfaces

API's to execute ENOVIA V5 VPM commands from ENOVIA V5 VPM NAvigator

Implementing ENOVIObjectServiceCode
Use Case

Abstract

The document is related to the use case CAAVpmPsEnovGetII. It describes how to implement a user-exit command which can be triggered from ENOVIA V5 VPM Navigator client using the new API's for running server code.


What You Will Learn With This Use Case

This use case is intended to help you implement the user-exit ENOVIObjectServiceCode that is called by the client API CATPDMCSServices::RunObjectService.

[Top]

The CAAVpmPsEnovGetII Use Case

CAAVpmPsEnovGetII is a use case of the CAAVpiInterfaces.edu framework that illustrates how to implement a server user-exit based on the API ENOVIObjectServiceCode, that is triggered by the ENOVIA V5 VPM Navigator client API  CATPDMCSServices::RunObjectService (See reference [2])

[Top]

What Does CAAVpmPsEnovGetII Do

The goal of the CAAVpmPsEnovGetII use case is to show how to implement the ENOVIObjectServiceCode user-exit and more precisely its method RunObjectServiceCode. It completes the explanations given in use case Manipulating a persistent ENOVIA object from within the ENOVIA V5 VPM Navigator environment (see reference [2]), which deals with the ENOVIA V5 VPM Navigator client side.

The RunObjectServiceCode user-exit implementation of the use case CAAVpmPsEnovGetII goes through the following steps:

[Top]

How to Launch CAAVpmPsEnovGetII

To launch CAAVpmPsEnovGetII, you will need to set up the build-time environment, compile CAAVpmPsEnovGetII along with its prerequisites and then, set up the run-time environment. CAAVpmPsEnovGetII is a server use case that is triggered from within the client use case named Manipulating a persistent ENOVIA object from within the ENOVIA V5 VPM Navigator environment (reference [2]); so finally you'll need to launch it and the execution of CAAVpmPsEnovGetII will follow automatically.

[Top]

Where to Find the CAAVpmPsEnovGetII Code

The CAAVpmPsEnovGetII use case is made of one class named CAAVpmPsEnovGetII located in the module CAAVpiServerCode.m of the framework CAAVPMInterfaces.edu.

Windows InstallRootDirectory\CAAVPMInterfaces.edu\CAAVpiServerCode.m\
Unix InstallRootDirectory/CAAVPMInterfaces.edu/CAAVpiServerCode.m/

Where InstallRootDirectory is the directory where the CAA CD-ROM is installed.

[Top]

Step-by-Step

The explanations of the CAAVpmPsEnovGetII implementation is split into five main steps:

  1. Implementing the ENOVIObjectServiceCode user-exit
  2. Retrieving the PRC and all the ItemInstances agregated under it
  3. Retrieving the input ItemInstance and its Part Version
  4. Selecting ItemInstances that shares the same Part Version than input ItemInstance

We will now comment each of these sections in detail.

[Top]

Implementing the ENOVIObjectServiceCode user-exit

To implement the user-exit, the class CAAVpmPsEnovGetII, has to be defined as a late type object that adheres to the ENOVIObjectServiceCode interface. This must be done with an extension mechanism, as shown by the lines below: the CATImplementClass instruction defines the CAAVpmPsEnovGetII class as a late type object identitified by the "GetII" string.

...
CATImplementClass(CAAVpmPsEnovGetII, DataExtension, CATBaseUnknown, GetII);
    ...

The relation/link between the interface and its implementation has to be precised. Here we have chosen to defined the CAAVpmPsEnovGetII class as a TIEchain implementation of the ENOVIObjectServiceCode interface.

...
#include "TIE_ENOVIObjectServiceCode.h"
TIEchain_ENOVIObjectServiceCode(CAAVpmPsEnovGetII);
    ...

The RunObjectServiceCode() method has to be implemented with respect of the following signature.

...
HRESULT CAAVpmPsEnovGetII::RunObjectServiceCode(CATLISTV(CATBaseUnknown_var)& iObjectIds,
                                                const char* ipString,
                                                CATLISTV(CATBaseUnknown_var)& oObjectIds,
                                                char** opString)
    ...

Concerning the method parameters... The [iObjectIds] input list contains an ItemInstance, the [ipString] input string gives the V_ID of the PRC that is investigated in the method, the [oObjectIds] ouput list is destinated to contain the ItemInstances sharing the same PartVersion than the ItemInstance given by [iObjectIds], and finally the [opString] output string will be keeping a NULL value along the whole treatment, as it has been chosen not to use it in this use case.

Finally, don't forget to add the following line into the dictionnary file (CAAVPMInterfaces.edu\CNext\code\dictionary\CAAVPMInterfaces.edu.dic) of the implementation framework.

...
GetII          ENOVIObjectServiceCode     libCAAVpiServerCode
    ...

The line is composed of the LateType of your implementation object: GetII, the name of Interface you want to implement: ENOVIObjectServiceCode and the library containing the implementation code libCAAVpiServerCode.

[Top]

Retrieving the PRC and all the ItemInstances agregated under it

Input String [ipString] (which is, in this use case, the "V_Id" of a PRC) is transformed in a CATUnicodeString which is given to the RetrievePRC. This method is able to retrieve a ProducRootClass from the ENOVIA V5 VPM database giving its "V_Id" attribute.

...
CATUnicodeString stPRCName = ipString;
CATIAVPMProductRootClass * pPRC = NULL;
rc = RetrievePRC(stPRCName, pPRC);
...

Once the PRC is retrieved, the get_Tree method is used to gather all ItemInstances inserted under the PRC.

...
#define PS_ALL        -1001
...
ENOVIExpandable_var spExpandPRC(pPRC);

if (spExpandPRC != NULL_var)
{
    CATLISTV(CATBaseUnknown_var) oListII;
    
    rc = spExpandPRC->get_Tree(PS_ALL, oListII);
...

[Top]

Retrieving the input ItemInstance and the V_Id of its Part Version

Three steps to be followed in this sections. Firstl, get the CATIAVPMItemInstance object from the input list [iObjectIds];
...
if (iObjectIds[1] != NULL_var)
{
  // 1. Retrieve the II
  CATIAVPMItemInstance * pII = NULL;
  rc = iObjectIds[1]->QueryInterface(IID_CATIAVPMItemInstance, (void**)&pII);

  if (FAILED(rc) || (pII == NULL))
  {
    cout << "**Error: QI for CATIAVPMItemInstance failed on [iObjectIds[1]]" << endl;
    rc = E_FAIL;
  }
...

Second, retrieve the PartVersion from the obtained VPM ItemInstance thanks to the CATIAVPMItemInstance::GetPartVersion;

...
// 2. Retrieve the PV
CATIAVPMPartVersion *pPV = NULL;
rc = pII->get_PartVersion(pPV);
pII->Release(); pII = NULL;

if (FAILED(rc) || !pPV)
{
  cout << "**Error: Unable to get PV of II [iObjectIds[1]]" << endl;
  rc = E_FAIL;
}
...

and finally get  the V_Id thanks to the CATIVpmBOAttribute::GetAttributeValue method.

...
  CATUnicodeString stPVName;
  rc = GetAttributeValue(pPV, "V_ID", stPVName);
  pPV->Release(); pPV = NULL;
  ...
}

HRESULT CAAVpmPsEnovGetII::GetAttributeValue(CATBaseUnknown *ipBase, CATUnicodeString stAttributeName, CATUnicodeString &oAttrValue)
{
  CATIVPMBOAttribute * pBOAttr = NULL;

  ...
  HRESULT rc = ipBase->QueryInterface(IID_CATIVPMBOAttribute, (void**)&pBOAttr);
  if (FAILED(rc) || (pBOAttr == NULL))
    return E_FAIL;

  CORBAAny cbAny;

  rc = pBOAttr->GetAttributeValue(stAttributeName,cbAny);

  pBOAttr->Release();
  pBOAttr = NULL;

  cbAny >> oAttrValue;
  ...
}

[Top]

Selecting ItemInstances that shares the same Part Version than input ItemInstance

From the list returned by the get_Tree method, II's are caught and their V_Id is compared with the one of the input Iteminstance. When the V_Id matches, the II of the list is added to the [oObjectIds] output list.

...
int countII = oListII.Size();

// Retrieve the PartVersion of each II
for (int i = 1; i <= countII; i++)
{
  if (oListII[i] != NULL_var)
  {
      CATIAVPMItemInstance *pII = NULL;
      rc = oListII[i]->QueryInterface(IID_CATIAVPMItemInstance, (void**)&pII);

      if (SUCCEEDED(rc) && pII != NULL)
      {
        // Retrieve the PV
        CATIAVPMPartVersion * pPartVersion = NULL;
        rc = pII->get_PartVersion(pPartVersion);

        if (SUCCEEDED(rc) && (pPartVersion != NULL))
        {
          // Retrieve the V_ID of the PV
          CATUnicodeString stIIPVname;
          rc = GetAttributeValue(pPartVersion, "V_ID", stIIPVname);
          pPartVersion->Release(); pPartVersion = NULL;

          if (SUCCEEDED(rc) && stIIPVname.GetLengthInChar() > 0)
          {
            // Compare the current V_ID with the one of the II given in input
            if (stIIPVname == stPVName)
            {
              cout << "Found an II of the same PV. Append it..." << endl;
              CATBaseUnknown_var unkObj(pII);

              if (!!unkObj) oObjectIds.Append(unkObj);
            }
          }
        }
        pII->Release(); pII = NULL;
      }
    }
}
...

[Top]


In Short

This use case demonstrates how the ENOVIObjectServiceCode::RunObjectServiceCode user-exit can be used to implement customized behavior on ENOVIA V5 VPM server. These business behaviors are triggered from within the CATIA V5/ENOVIA V5 VPM Navigator client thanks to the CATPDMCSServices::RunObjectService API.
(See Manipulating a persistent ENOVIA object from within the ENOVIA V5 VPM Navigator environment use case in CAACATImmENOVIAProviderDoc.edu/CAAImmUseCases.doc/src/CAAImmEV5CV5BindTestCmd.htm)
As an example, a user-exit is implemented to retrieve from a ProductRootClass all the ItemInstances sharing the same Part Version.

[Top]


References

[1] Building and Launching a CAA V5 Use Case
[2] Client Use case Manipulating an ENOVIA Item Instance from within the ENOVIA V5 VPM Navigator environment in CAACATImmENOVIAProviderDoc.edu/CAAImmUseCases.doc/src/CAAImmEV5CV5BindTestCmd.htm
[Top]

History

Version: 1 [May 2007] Document created
[Top]

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