Tuesday, 20 December 2016

Teamcenter ITK : Custom Exit : Sample

Problem statement: Write custom exit which will register a function to get executed before checkin of the object.If the object is of type CATProduct/CATPart/DirectModel/CATDrawng then get it's detail.

sample.c

#include <tc/tc.h>
#include <custom.h>
#include <dataset.h>
#include <epm/epm.h>
#include <ict_userservice.h>
#include <method.h>
#include <property/prop.h>
#include <property/prop_errors.h>
#include <property/prop_msg.h>
#include <reservation.h>
#include <stdarg.h>
#include <string.h>
#include <tc.h>
#include <tc/emh_const.h>
#include <tc/envelope.h>
#include <tc/emh.h>
#include <tccore/aom.h>
#include <tccore/aom_prop.h>
#include <tccore/custom.h>
#include <tccore/item.h>
#include <tccore/item_errors.h>
#include <tccore/item_msg.h>
#include <tccore/method.h>
#include <tccore/tctype.h>
#include <tccore/workspaceobject.h>
#include <tcfile.h>
#include <tctype.h>
#include <item_errors.h>
#include <user_exits/user_exits.h>
#include <workspaceobject.h>

//This method called on custom library load
//This function will get executed when teamcenter start as TC will load the libraries
//This function register checkin_register_method
//Once this function get a call ,it will call checkin_register_method

extern DLLAPI int checkin_register_callbacks ()
{
    if(CUSTOM_register_exit ( "checkin", "USER_init_module", (CUSTOM_EXIT_ftn_t)                    checkin_register_method) !=ITK_ok);
     PrintErrorStack();
  return ( ITK_ok );
}
static int PrintErrorStack( void )
{

    int iNumErrs = 0;
    int *pSevLst = NULL;
    int *pErrCdeLst = NULL;
    char **pMsgLst = NULL;

    register int i = 0;

    // Gives the severities, ifail codes, and associated internationalized texts for each error on the error store.

    EMH_ask_errors( &iNumErrs, &pSevLst, &pErrCdeLst, &pMsgLst );
    fprintf( stderr, "Error(s): \n");
    for ( i = 0; i < iNumErrs; i++ )
    {
       fprintf( stderr, "\t%6d: %s\n", pErrCdeLst[i], pMsgLst[i] );

    }
    return ITK_ok;
}
//This function will register method to be executed before check in of the object
extern int checkin_register_method(int *decision, va_list args)
{
    METHOD_id_t  method;
   *decision = ALL_CUSTOMIZATIONS;

      //Find the method  object for Reservstion class checkin message 
     //Looks for the registered method
    //used to implement the specified type/message combination.
   //This is useful for registering pre- or post-actions or a pre-condition for a method created elsewhere in the system
    if ( METHOD_find_method(RES_Type, RES_checkin_msg, &method) !=ITK_ok)
      PrintErrorStack();

   // If method_id.id == 0 , it implies, that we do not have methods
    if (method.id != NULLTAG)
    {   //Register method for pre action of checkin message
 //METHOD_function_t is user defined structure
        if( METHOD_add_action(method, METHOD_pre_action_type, (METHOD_function_t) checkin_method_1, NULL)!=ITK_ok)
        PrintErrorStack();
    }
    else
        TC_write_syslog("Method not found!");

  return ITK_ok;
}

//Actual method executed as pre action of checkin
//All functions registered as base, pre or post actions, or pre condition handlers must be of this type.
extern DLLAPI int checkin_method_1(METHOD_message_t *m, va_list args)
{
    //var_arg will get the argument in sequence
    tag_t objTag = va_arg(args, tag_t);
    tag_t  reln_type =NULLTAG;
    int    n_attchs,i=0,referencenumberfound=0,j=0;
    AE_reference_type_t     reftype;
    char   *ret_id,*ret_rev;
    tag_t  *secondary_objects,primary,refobject,objTypeTag,objTypeTag1=NULLTAG;
    char   refname[AE_reference_size_c + 1];
    char   orig_name[IMF_filename_size_c + 1];
    char   path_name[SS_MAXPATHLEN];
    char   type_name[TCTYPE_name_size_c+1];
    char   type_name1[TCTYPE_name_size_c+1];
    char  relative_path[IMF_relative_path_size_c+1];
    char errorString[100]="Check in error";
    EPM_decision_t decision=EPM_go;
    
    if (TCTYPE_ask_object_type(objTag,&objTypeTag1)!=ITK_ok)PrintErrorStack();
    if (TCTYPE_ask_name(objTypeTag1,type_name1)!=ITK_ok)PrintErrorStack();
    if( EMH_clear_errors( )!= ITK_ok ) // Emtpy the error stack
      PrintErrorStack();

     if(strcmp(type_name1,"Text")==0 )
     {
         ERROR_CALL(EMH_store_error_s1(EMH_severity_error,ITK_err,"TEXT"));
 return "error";
     }
     if(strcmp(type_name1,"CATProduct")==0 || strcmp(type_name1,"CATPart")==0 ||  strcmp(type_name1,"CATDrawing")==0 || strcmp(type_name1,"DirectModel")==0)
     {
 ECHO("\n inside my required classssssssssss= \n");
     if (AE_ask_dataset_id_rev(objTag,&ret_id,&ret_rev)!=ITK_ok)PrintErrorStack();
   if (AE_ask_dataset_ref_count(objTag,&referencenumberfound)!=ITK_ok)PrintErrorStack();

        for(j=0;j<referencenumberfound;j++)
        {

    if (AE_find_dataset_named_ref(objTag,j,refname,&reftype,&refobject)!=ITK_ok)PrintErrorStack();
           if ( IMF_ask_original_file_name(refobject,orig_name)!=ITK_ok)PrintErrorStack();
           printf("\n orig_name is :%s\n",orig_name);
       if(IMF_ask_file_pathname(refobject,SS_WNT_MACHINE,path_name)!=ITK_ok)PrintErrorStack();
      printf("\n path_name is :%s\n",path_name);
     if(IMF_ask_relative_path(refobject,relative_path)!=ITK_ok)PrintErrorStack();
        }

      }
     /* Add required validation skkkkk */
      report_object_description(objTag);
      
    return ITK_ok;
}
static void report_object_description(tag_t object)
{
    WSO_description_t desc;
    tag_t  sequence_id_c;
    //Returns a structure containing basic information about a workspace 
   //object. This is a convenience function, as all of this information can 
   //also be obtained using other POM, AOM and WSOM functions.
  //All of the values, except the revision number, are returned as strings. 
   if (WSOM_describe(object, &desc) !=ITK_ok)   PrintErrorStack();
   printf("Object Name:%s\n", desc.object_name);
}
//END OF CODE

What below section of code does in above code?
Please read comment in the code...
//Dataset related API will be present in Application Encapsulation module
//This will find the dataset id and rev
//Dataset is the container for actual files ,which are stored as named reference
if (AE_ask_dataset_id_rev(objTag,&ret_id,&ret_rev)!=ITK_ok)PrintErrorStack();
//Find the number of files present in the dataset
if (AE_ask_dataset_ref_count(objTag,&referencenumberfound)!=ITK_ok)PrintErrorStack();


//Loop over the reference count to get the file
for(j=0;j<referencenumberfound;j++)
{ 
   //get the referenced objects at index
   if (AE_find_dataset_named_ref(objTag,j,refname,&reftype,&refobject)!=ITK_ok)PrintErrorStack();
   //get the original file named
   if ( IMF_ask_original_file_name(refobject,orig_name)!=ITK_ok)PrintErrorStack();

 printf("\n orig_name is :%s\n",orig_name);

   //Returns the full pathname of the physical file on disk associated
   //The format of the pathname will depend on the value of machine_type, it will be either SS_WNT_MACHINE or SS_UNIX_MACHINE.
   if(IMF_ask_file_pathname(refobject,SS_WNT_MACHINE,path_name)!=ITK_ok)PrintErrorStack();
   printf("\n path_name is :%s\n",path_name);//
   if(IMF_ask_relative_path(refobject,relative_path)!=ITK_ok)PrintErrorStack();

}

Explanation : Important API 
METHOD_find_method(RES_Type, RES_checkin_msg, &method) 
METHOD_add_action(method, METHOD_pre_action_type, (METHOD_function_t) checkin_method_1, NULL) 
AE_ask_dataset_ref_count(objTag,&referencenumberfound) AE_find_dataset_named_ref(objTag,j,refname,&reftype,&refobject) IMF_ask_file_pathname(refobject,SS_WNT_MACHINE,path_name) IMF_ask_relative_path(refobject,relative_path)

No comments:

Post a Comment