/*****************************************************************************
 * File:  EXP_T_object.c
 *
 * Object:     technique  (T)
 * Subsystem:  experiment
 * Domain:     EXP
 * Repository: exp.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 "EXP_objects.h"
#include "EXP_T_object.h"
#include "EXP_T_events.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.
 ****************************************************************************/
/* 4000 */
static EXP_T_s EXP_T_ObjectPool_s[ EXP_T_MAX_EXTENT_SIZE ];
/* 4000 */
static Escher_ObjectSet_s EXP_T_ActiveExtent_s; /* set container */
Escher_ObjectSet_s * pG_EXP_T_extent;
static Escher_ObjectSet_s * p_EXP_T_inanimate;

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

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


/*****************************************************************************
 * Object Creation Accessor
 ****************************************************************************/
EXP_T_s *
EXP_T_Create()
{
  Escher_ObjectSet_s * node;
  EXP_T_s * self;

  /* Check if object pool is empty.  */
  if ( !p_EXP_T_inanimate ) {
    UserObjectPoolEmptyCallout( "exp", "technique" );
    return (EXP_T_s *) 0;
  }

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

  /* Initialize application analysis object attributes.  */
  self->m_T_ID = (Escher_UniqueID_t) self;
  self->m_start = 0;
  self->m_end = 0;
  self->m_number_of_batches = 0;
  self->m_current_batch = 0;

  self->mc_current_state = EXP_T_STATE_1;

  /* Insert instance into active extent (animate).  */
  node->next = pG_EXP_T_extent->next;
  pG_EXP_T_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
EXP_T_StateEventMatrix[3][3] =
{
  /* Row 0: 'Unitialized' */
  { EVENT_CANT_HAPPEN, EVENT_CANT_HAPPEN, EVENT_CANT_HAPPEN },
  /* Row 1: EXP_T_STATE_1 'idle' */
  { EXP_T_STATE_2, EVENT_IS_IGNORED, EVENT_IS_IGNORED },
  /* Row 2: EXP_T_STATE_2 'running' */
  { EVENT_IS_IGNORED, EXP_T_STATE_2, EXP_T_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
EXP_T_Actions[3] =
{
  (StateAction_t) 0,
  (StateAction_t) EXP_T_Action_1,  /* 'idle' */
  (StateAction_t) EXP_T_Action_2   /* 'running' */
};

/*****************************************************************************
 * EXP_T_Dispatch - State model level event dispatching.
 ****************************************************************************/
void
EXP_T_Dispatch( const OoaEvent_t * const event )
{
  EXP_T_s * instance = (EXP_T_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 = EXP_T_StateEventMatrix[ current_state ][ event_number ];
      if ( next_state <= 2 )
      {
        /* Execute the state action and update 'current state' */
        ( *EXP_T_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 */
        }
      }
    }
  }
}