/*****************************************************************************
 * File:  A_CAR_object.c
 *
 * Object:     carousel  (CAR)
 * 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_CAR_object.h"
#include "A_CAR_events.h"
#include "A_ROW_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_CAR_s A_CAR_ObjectPool_s[ A_CAR_MAX_EXTENT_SIZE ];
static Escher_ObjectSet_s A_CAR_ActiveExtent_s; /* set container */
Escher_ObjectSet_s * pG_A_CAR_extent;
static Escher_ObjectSet_s * p_A_CAR_inanimate;

/*****************************************************************************
 * Initialize object factory services.
 ****************************************************************************/
void
A_CAR_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_CAR_MAX_EXTENT_SIZE; i++ )
  {
    Escher_SetInsertElement( &s, &A_CAR_ObjectPool_s[ i ] );
  }
  p_A_CAR_inanimate = s.next; /* free list head */

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


/*****************************************************************************
 * Object Creation Accessor
 ****************************************************************************/
A_CAR_s *
A_CAR_Create()
{
  Escher_ObjectSet_s * node;
  A_CAR_s * self;

  /* Check if object pool is empty.  */
  if ( !p_A_CAR_inanimate ) {
    UserObjectPoolEmptyCallout( "as2", "carousel" );
    return (A_CAR_s *) 0;
  }

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

  /* Initialize application analysis object attributes.  */
  self->m_carousel_ID = 0;
  self->m_destination = 0;
  self->m_current_position = 0;

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

  self->mc_current_state = A_CAR_STATE_1;

  /* Insert instance into active extent (animate).  */
  node->next = pG_A_CAR_extent->next;
  pG_A_CAR_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_CAR_StateEventMatrix[3][2] =
{
  /* Row 0: 'Unitialized' */
  { EVENT_CANT_HAPPEN, EVENT_CANT_HAPPEN },
  /* Row 1: A_CAR_STATE_1 'resting' */
  { A_CAR_STATE_2, EVENT_IS_IGNORED },
  /* Row 2: A_CAR_STATE_2 'going' */
  { EVENT_IS_IGNORED, A_CAR_STATE_1 }
};

/*****************************************************************************
 * 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_CAR_Actions[3] =
{
  (StateAction_t) 0,
  (StateAction_t) A_CAR_Action_1,  /* 'resting' */
  (StateAction_t) A_CAR_Action_2   /* 'going' */
};

/*****************************************************************************
 * A_CAR_Dispatch - State model level event dispatching.
 ****************************************************************************/
void
A_CAR_Dispatch( const OoaEvent_t * const event )
{
  A_CAR_s * instance = (A_CAR_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 > 2 )
    {
      /* Instance validation failure (deleted while event in flight) - TBD */
    }
    else
    {
      next_state = A_CAR_StateEventMatrix[ current_state ][ event_number ];
      if ( next_state <= 2 )
      {
        /* Execute the state action and update 'current state' */
        ( *A_CAR_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 */
        }
      }
    }
  }
}