
/*  File: arfilterapisamp.c  */

#ifdef _WIN32
#include <windows.h>
#endif /* _WIN32 */

#include <stdlib.h>
#include <string.h>

#include "arfilterapi.h"

/*****************************************************************************/
/*                                                                           */
/*                 Action Request System Filter API Sample                   */
/*                                                                           */
/*****************************************************************************/
/* Description: This is a sample filter API plug-in.  It is intended for use */
/*    by AR System customers in implementing a customized filter API plug-in.   */
/*                                                                           */
/*    This sample assigns the input values from the input value list to the  */
/*    output value list.                                                     */
/*    The memory passed in in the input value list as well as the memory     */
/*    returned in the output value list will be freed by the RPC layer,      */
/*    so memory may only be pointed to by one of the lists.                  */
/*    Please note that the input value list is set to null after it is       */
/*    assigned in order to avoid a double free of the memory.                */
/*                                                                           */
/*****************************************************************************/

#ifdef _WIN32
                        /* DllMain is only required in Windows environments. */

BOOL APIENTRY DllMain(HANDLE hModule, 
                      DWORD  ul_reason_for_call, 
                      LPVOID lpReserved)
{
   return TRUE;
}
#endif /* _WIN32 */


/*****************************************************************************/
/*                                                                           */
/*                             ARPluginIdentify                              */
/*                                                                           */
/*****************************************************************************/
/* Description: This function is called by the plug-in service to identify   */
/*    what type of plug-in this implements.                                  */
/*                                                                           */
/*****************************************************************************/

ARPLUGIN_EXPORT int ARPluginIdentify(
ARPluginIdentification      *id,     /* OUT; information about the plug-in */
ARStatusList                *status  /* OUT; error message(s)*/
)
{
   id->type = AR_PLUGIN_TYPE_FILTER;
   strcpy(id->name, "EXAMPLE.ARF.SIMPLE");
   id->version = ARFILTERAPI_PLUGIN_VERSION;
   memset(status, 0, sizeof(*status));

   return AR_RETURN_OK;
}


/*****************************************************************************/
/*                                                                           */
/*                        ARPluginSetProperties                              */
/*                                                                           */
/*****************************************************************************/
/* Description: This function is called by the plug-in service to pass along */
/*    information about various properties or facilities that the plug-in    */
/*    should be aware of.                                                    */
/*                                                                           */
/*****************************************************************************/

ARPLUGIN_EXPORT int ARPluginSetProperties(
ARPropList      *propList,  /* IN; properties from the plug-in service */
ARStatusList    *status     /* OUT; error message(s)*/
)
{
   unsigned int i;
   void *fptr;
   AR_PLUGIN_LOG_FUNCTION logFunc = NULL;
   ARPluginIdentification id;

   if (propList == NULL)
      return AR_RETURN_OK;

   for (i = 0; i < propList->numItems; i++)
   {
      switch(propList->props[i].prop)
      {
      case AR_PLUGIN_PROP_LOG_FUNCTION:
        /* Identify the pointer to the logging function for this
         * version of plug-in
         */
         if (propList->props[i].value.dataType == AR_DATA_TYPE_BYTES &&
             propList->props[i].value.u.byteListVal != NULL)
         {
            memcpy(&fptr,
                   (void*)propList->props[i].value.u.byteListVal->bytes,
                   sizeof(void *));
            logFunc = (AR_PLUGIN_LOG_FUNCTION)fptr;
         }
         break;
      default:
         break;
      }
   }

   /* Show how to use the logging facility. */
   if (logFunc != NULL)
   {
      id.type = AR_PLUGIN_TYPE_FILTER;
      strcpy(id.name, "EXAMPLE.ARF.SIMPLE");
      id.version = ARFILTERAPI_PLUGIN_VERSION;

      (*logFunc)(&id, AR_PLUGIN_LOG_INFO, "ARPluginSetProperties called");
   }

   return AR_RETURN_OK;
}

/*****************************************************************************/
/*                                                                           */
/*                          ARPluginInitialization                           */
/*                                                                           */
/*****************************************************************************/
/* Description: This function is called by the plug-in service to initilize  */
/*    the plug-in.  This is where the plug-in should initialize any data     */
/*    that will be global and accessed by all instances of the plug-in that  */
/*    are created via ARPluginCreateInstance().                              */
/*                                                                           */
/*****************************************************************************/

ARPLUGIN_EXPORT int ARPluginInitialization(
int                argc,  /*  IN; argc from main() */
char             **argv,  /*  IN; argv from main() */
ARStatusList      *status
)
{
   if (status != NULL)
      memset(status, 0, sizeof(*status));

   return AR_RETURN_OK;
}


/*****************************************************************************/
/*                                                                           */
/*                          ARPluginTermination                              */
/*                                                                           */
/*****************************************************************************/
/* Description: This function is called by the plug-in service to terminate  */
/*    the plug-in.  This is where the plug-in should deallocate any          */
/*    resources that have been allocated either globally or by each instance */
/*    created by ARPluginCreateInstance().                                   */
/*                                                                           */
/*****************************************************************************/

ARPLUGIN_EXPORT int ARPluginTermination(
ARStatusList *status
)
{
   if (status != NULL)
      memset(status, 0, sizeof(*status));
   
   return AR_RETURN_OK;
}


/*****************************************************************************/
/*                                                                           */
/*                          ARPluginCreateInstance                           */
/*                                                                           */
/*****************************************************************************/
/* Description: This function is called by the plug-in service to create an  */
/*    instance of the plug-in.  Each instance is guaranteed to be involved   */
/*    in one thread of operation at any one time.                            */
/*                                                                           */
/*    The structure returned via the 'object' pointer will be provided in    */
/*    subsequent plug-in calls.  This allows you to attach arbitrary data    */
/*    to an instance that will be inherently thread safe.                    */
/*                                                                           */
/*****************************************************************************/

ARPLUGIN_EXPORT int ARPluginCreateInstance(
void           **object,
ARStatusList    *status
)
{
   if (status != NULL)
      memset(status, 0, sizeof(*status));

   if (object != NULL)
   {
      /*
       * Set *object to point to something that you have 
       * allocated and initialized.
       */
      *object = NULL;
   }

   return AR_RETURN_OK;
}


/*****************************************************************************/
/*                                                                           */
/*                          ARPluginDeleteInstance                           */
/*                                                                           */
/*****************************************************************************/
/* Description: This function is called by the plug-in service to delete an  */
/*    instance of the plug-in.  Each instance is guaranteed to be involved   */
/*    in one thread of operation at any one time.                            */
/*                                                                           */
/*****************************************************************************/

ARPLUGIN_EXPORT int ARPluginDeleteInstance(
void           *object,
ARStatusList   *status
)
{
   if (object != NULL)
   {
      /*
       * Anything that you allocated in ARPluginCreateInstance
       * should be deallocated here.
       */
   }

   return AR_RETURN_OK;
}


/*****************************************************************************/
/*                                                                           */
/*                               ARFilterApiCall                             */
/*                                                                           */
/*****************************************************************************/
/* Description: This function is called whenever a request is made by the AR */
/*    System Server to the filter api.                                       */
/*                                                                           */
/*    The input values are passed as parameters.                             */
/*                                                                           */
/*    A customized filter api plug-in must define this function.  Any        */
/*    global information or resources accessed here must be protected with   */
/*    appropriate mutual exclusion locks to be multi-thread safe.            */
/*                                                                           */
/*    A customized filter api plug-in may return outValues and/or status.    */
/*    An error in the status parameter will be passed to the workflow and    */
/*    stop filter processing.                                                */
/*    A status of type AR_RETURN_ERROR will cause the calling filter to fail.*/
/*    A status of type AR_RETURN_WARNING will be passed to the AR server     */
/*    client.                                                                */
/*                                                                           */
/*    All memory in inValues and all memory returned via outValues and       */
/*    status will be freed by the RPC layer.                                 */
/*                                                                           */
/*****************************************************************************/

ARPLUGIN_EXPORT void ARFilterApiCall(
void                   *object,
ARValueList            *inValues,
ARValueList            *outValues,
ARStatusList            *status
)
{
   unsigned int          i;

   outValues->numItems = inValues->numItems;
   outValues->valueList = calloc (1, sizeof(ARValueStruct) *
                                            outValues->numItems);
   /* If we have input values then assign them to the output value list, */
   /* Because the ARValueStruct may contain pointers to allocated memory */
   /* we set the entire ARValueStruct to NULL after copying it.  The RPC */
   /* layer will not free a NULL pointer.                                */
   if (outValues->valueList == NULL)
      outValues->numItems = 0;
   else
   {
      for (i = 0; i < outValues->numItems; i++)
      {
         outValues->valueList[i] = inValues->valueList[i];
         memset(&inValues->valueList[i], 0, sizeof(ARValueStruct));
      }
   }

   /* If outValue[0] is a string value then compare against error and warning. */
   /* otherwise return no status entry.                                       */
   if (outValues->numItems && outValues->valueList &&
       outValues->valueList[0].dataType == AR_DATA_TYPE_CHAR &&
       status != NULL)
   {
      if (strcmp(outValues->valueList[0].u.charVal, "warning") == 0)
      {
         status->numItems = 1;
         status->statusList = (ARStatusStruct *) calloc(1, sizeof(ARStatusStruct));
         status->statusList[0].messageType = AR_RETURN_WARNING;
         /* Please observe the AR System reserved ranges for message numbers as */
         /* documented and indicated in the arerrno.h file.                  */
         status->statusList[0].messageNum = 88888;
         status->statusList[0].messageText = strdup("Plugin received message");
         status->statusList[0].appendedText = strdup(outValues->valueList[0].u.charVal);
      }
      else if (strcmp(outValues->valueList[0].u.charVal, "error") == 0)
      {
         status->numItems = 1;
         status->statusList = (ARStatusStruct *) calloc(1, sizeof(ARStatusStruct));
         status->statusList[0].messageType = AR_RETURN_ERROR;
         /* Please observe the AR System reserved ranges for message numbers as */
         /* documented and indicated in the arerrno.h file.                  */
         status->statusList[0].messageNum = 99999;
         status->statusList[0].messageText = strdup("Plugin received message");
         status->statusList[0].appendedText = strdup(outValues->valueList[0].u.charVal);
      }
   }

   return;
}
