/*****************************************************************************
 * File:  A_SP_object.c
 *
 * Object:     sampling_probe  (SP)
 * Subsystem:  autosampler
 * Domain:     A
 * Repository: as2.ooa
 *
 * Notice:
 *   (C) Copyright 1999, 2000 ROX Software, Inc.
 *   All rights reserved.
 *
 * Model Compiler:  MC3020 V1.3.0
 *
 * Warnings:
 *   !!! THIS IS AN AUTO-GENERATED FILE. PLEASE DO NOT EDIT. !!!
 ****************************************************************************/

#include "A_objects.h"
#include "A_SP_object.h"
#include "A_SP_events.h"
#include "A_ROW_object.h"
#include "A_PAA_object.h"
    
/*****************************************************************************
 * Statically allocate space for the instance population for this object.
 * Allocate space for the object and its attributes.
 * Depending on the collection scheme, allocate containoids (collection
 * nodes) for gathering instances into free and active extents.
 ****************************************************************************/
static A_SP_s A_SP_ObjectPool_s[ A_SP_MAX_EXTENT_SIZE ];
static Escher_ObjectSet_s A_SP_ActiveExtent_s; /* set container */
Escher_ObjectSet_s * pG_A_SP_extent;
static Escher_ObjectSet_s * p_A_SP_inanimate;

/*****************************************************************************
 * Initialize object factory services.
 ****************************************************************************/
void
A_SP_FactoryInit()
{
  unsigned int i;
  Escher_ObjectSet_s s;
  Escher_InitSet( &s );

  /* Initialize object instance storage free pool (inanimate list)
   * by linking the containoids into a linear, null-terminated,
   * singly linked list.  */
  for ( i = 0; i < A_SP_MAX_EXTENT_SIZE; i++ )
  {
    Escher_SetInsertElement( &s, &A_SP_ObjectPool_s[ i ] );
  }
  p_A_SP_inanimate = s.next; /* free list head */

  /* Initialize object class extent (animate list) to empty.  */
  Escher_InitSet( &A_SP_ActiveExtent_s );
  pG_A_SP_extent = &A_SP_ActiveExtent_s;
}


/*****************************************************************************
 * Object Creation Accessor
 ****************************************************************************/
A_SP_s *
A_SP_Create()
{
  Escher_ObjectSet_s * node;
  A_SP_s * self;

  /* Check if object pool is empty.  */
  if ( !p_A_SP_inanimate ) {
    UserObjectPoolEmptyCallout( "as2", "sampling_probe" );
    return (A_SP_s *) 0;
  }

  /* Acquire instance storage from object free pool.  */
  node = p_A_SP_inanimate;
  p_A_SP_inanimate = p_A_SP_inanimate->next;
  self = (A_SP_s *) node->object;

  /* Initialize application analysis object attributes.  */
  self->m_probe_ID = 0;
  self->m_radial_position = 0;
  self->m_theta_offset = 0;
  self->m_current_position = 0;
  self->m_available = false;

  /* Initialize relationship storage */
  self->mc_PAA_R2 = 0;

  self->mc_current_state = A_SP_STATE_1;

  /* Insert instance into active extent (animate).  */
  node->next = pG_A_SP_extent->next;
  pG_A_SP_extent->next = node;

  return self;
}



/*****************************************************************************
 * State-Event Matrix (SEM)
 * Row Index is object's current (MC enumerated) current state.
 * Row zero is the unitialized state (e.g., for creation event transitions).
 * Column Index is (MC enumerated) state machine events.
 *****************************************************************************/
static const Escher_StateNumber_t
A_SP_StateEventMatrix[5][3] =
{
  /* Row 0: 'Unitialized' */
  { EVENT_CANT_HAPPEN, EVENT_CANT_HAPPEN, EVENT_CANT_HAPPEN },
  /* Row 1: A_SP_STATE_1 'up' */
  { EVENT_IS_IGNORED, A_SP_STATE_4, EVENT_IS_IGNORED },
  /* Row 2: A_SP_STATE_2 'down' */
  { A_SP_STATE_3, EVENT_IS_IGNORED, EVENT_IS_IGNORED },
  /* Row 3: A_SP_STATE_3 'raising' */
  { EVENT_IS_IGNORED, EVENT_IS_IGNORED, A_SP_STATE_1 },
  /* Row 4: A_SP_STATE_4 'lowering' */
  { EVENT_IS_IGNORED, EVENT_IS_IGNORED, A_SP_STATE_2 }
};

/*****************************************************************************
 * Array of pointers to the object's state action methods.
 * Index is the (MC enumerated) number of the state action method to execute.
 ****************************************************************************/
static const StateAction_t
A_SP_Actions[5] =
{
  (StateAction_t) 0,
  (StateAction_t) A_SP_Action_1,  /* 'up' */
  (StateAction_t) A_SP_Action_2,  /* 'down' */
  (StateAction_t) A_SP_Action_3,  /* 'raising' */
  (StateAction_t) A_SP_Action_4   /* 'lowering' */
};

/*****************************************************************************
 * A_SP_Dispatch - State model level event dispatching.
 ****************************************************************************/
void
A_SP_Dispatch( const OoaEvent_t * const event )
{
  A_SP_s * instance = (A_SP_s *)GetEventTargetInstance( event );
  Escher_EventNumber_t event_number = GetOoaEventNumber( event );
  Escher_StateNumber_t current_state;
  Escher_StateNumber_t next_state;

  if ( instance )
  {
    current_state = instance->mc_current_state;
    if ( current_state > 4 )
    {
      /* Instance validation failure (deleted while event in flight) - TBD */
    }
    else
    {
      next_state = A_SP_StateEventMatrix[ current_state ][ event_number ];
      if ( next_state <= 4 )
      {
        /* Execute the state action and update 'current state' */
        ( *A_SP_Actions[ next_state ] )( instance, event );
        instance->mc_current_state = next_state;
      }
      else
      {
        if ( next_state == EVENT_CANT_HAPPEN )
        {
          /* Event can't happen */
          UserEventCantHappenCallout( current_state, next_state, event_number );
        }
        else if ( next_state == EVENT_IS_IGNORED )
        {
          /* Event ignored */
        }
        else
        {
          /* Translation/memory/stack error, etc - TBD */
        }
      }
    }
  }
}