const char *DynamicConsoleMethodComponent::callOnBehaviors( U32 argc, const char *argv[] )
{
   // Set Owner
   SimObject *pThis;
   pThis = dynamic_cast<SimObject *>( this );
   AssertFatal( pThis, "DynamicConsoleMethodComponent::callOnBehaviors : this should always exist!" );

   const char* result = "";
   bool handled = false;

   if( getComponentCount() > 0 )
   {
      VectorPtr<SimComponent *>&componentList = lockComponentList();
      for( SimComponentIterator nItr = (componentList.end()-1);  nItr >= componentList.begin(); nItr-- )
      {
         argv[0] = StringTable->insert(argv[0]);

         SimComponent *pComponent = (*nItr);
         AssertFatal( pComponent, "DynamicConsoleMethodComponent::callOnBehaviors - NULL component in list!" );

         handled = pComponent->callMethodOnComponents(argc, argv, &result);
         if (handled)
            break;
      }
      unlockComponentList();
   }

   if (!handled)
   {
      result = "ERR_CALL_NOT_HANDLED";
   }

   return result;
}
//-----------------------------------------------------------
// Function name:  SimComponent::handlesConsoleMethod
// Summary:
//-----------------------------------------------------------
bool DynamicConsoleMethodComponent::handlesConsoleMethod( const char *fname, S32 *routingId )
{
   // CodeReview: Host object is now given priority over components for method
   // redirection. [6/23/2007 Pat]

   // On this object?
   if( isMethod( fname ) )
   {
      *routingId = -1; // -1 denotes method on object
      return true;
   }

   // on this objects components?
   S32 nI = 0;
   VectorPtr<SimComponent*> &componentList = lockComponentList();
   for( SimComponentIterator nItr = componentList.begin(); nItr != componentList.end(); nItr++, nI++ )
   {
      SimObject *pComponent = dynamic_cast<SimObject*>(*nItr);
      if( pComponent != NULL && pComponent->isMethod( fname ) )
      {
         *routingId = -2; // -2 denotes method on component
         unlockComponentList();
         return true;
      }
   }
   unlockComponentList();

   return false;
}
bool SimComponent::_registerComponents( SimComponent *owner )
{
   // This method will return true if the object contains no components. See the
   // documentation for SimComponent::onComponentRegister for more information
   // on this behavior.
   bool ret =  true;

   // If this doesn't contain components, don't even lock the list.
   if( hasComponents() )
   {
      VectorPtr<SimComponent *> &components = lockComponentList();
      for( SimComponentIterator i = components.begin(); i != components.end(); i++ )
      {
         if( !(*i)->onComponentRegister( owner ) )
         {
            ret = false;
            break;
         }

         AssertFatal( (*i)->mOwner == owner, "Component failed to call parent onComponentRegister!" );

         // Recurse
         if( !(*i)->_registerComponents( owner ) )
         {
            ret = false;
            break;
         }
      }

      unlockComponentList();
   }

   return ret;
}
void SimComponent::_registerInterfaces( SimComponent *owner )
{
   // First call this to expose the interfaces that this component will cache
   // before examining the list of subcomponents
   registerInterfaces( owner );

   // Early out to avoid mutex lock and such
   if( !hasComponents() )
      return;

   VectorPtr<SimComponent *> &components = lockComponentList();
   for( SimComponentIterator i = components.begin(); i != components.end(); i++ )
   {
      (*i)->mOwner = owner;

      // Tell the component itself to register it's interfaces
      (*i)->registerInterfaces( owner );

      (*i)->mOwner = NULL; // This tests to see if the object's onComponentRegister call will call up to the parent.

      // Recurse
      (*i)->_registerInterfaces( owner );
   }

   unlockComponentList();
}
void SimComponent::_unregisterComponents()
{
   if( !hasComponents() )
      return;

   VectorPtr<SimComponent *> &components = lockComponentList();
   for( SimComponentIterator i = components.begin(); i != components.end(); i++ )
   {
      (*i)->onComponentUnRegister();

      AssertFatal( (*i)->mOwner == NULL, "Component failed to call parent onUnRegister" );

      // Recurse
      (*i)->_unregisterComponents();
   }

   unlockComponentList();
}
void SimComponent::onRemove()
{
    _unregisterComponents();

    // Delete all components
    VectorPtr<SimComponent *>&componentList = lockComponentList();
    while(componentList.size() > 0)
    {
        SimComponent *c = componentList[0];
        componentList.erase( componentList.begin() );

        if( c->isProperlyAdded() )
            c->deleteObject();
        else if( !c->isRemoved() && !c->isDeleted() )
            delete c;
        // else, something else is deleting this, don't mess with it
    }
    unlockComponentList();

    Parent::onRemove();
}
// Call all components that implement methodName giving them a chance to operate
// Components are called in reverse order of addition
const char *DynamicConsoleMethodComponent::_callMethod( U32 argc, const char *argv[], bool callThis /* = true  */ )
{
   // Set Owner
   SimObject *pThis = dynamic_cast<SimObject *>( this );
   AssertFatal( pThis, "DynamicConsoleMethodComponent::callMethod : this should always exist!" );

   const char *cbName = StringTable->insert(argv[0]);

   if( getComponentCount() > 0 )
   {
      VectorPtr<SimComponent *>&componentList = lockComponentList();
      for( SimComponentIterator nItr = (componentList.end()-1);  nItr >= componentList.begin(); nItr-- )
      {
         argv[0] = cbName;

         SimComponent *pComponent = (*nItr);
         AssertFatal( pComponent, "DynamicConsoleMethodComponent::callMethod - NULL component in list!" );

         DynamicConsoleMethodComponent *pThisComponent = dynamic_cast<DynamicConsoleMethodComponent*>( pComponent );
         AssertFatal( pThisComponent, "DynamicConsoleMethodComponent::callMethod - Non DynamicConsoleMethodComponent component attempting to callback!");

         // Only call on first depth components
         // Should isMethod check these calls?  [11/22/2006 justind]
         if(pComponent->isEnabled())
            Con::execute( pThisComponent, argc, argv );

         // Bail if this was the first element
         //if( nItr == componentList.begin() )
         //   break;
      }
      unlockComponentList();
   }
   
   // Set Owner Field
   const char* result = "";
   if(callThis)
      result = Con::execute( pThis, argc, argv, true ); // true - exec method onThisOnly, not on DCMCs

   return result;
}
bool SimComponent::callMethodOnComponents( U32 argc, const char* argv[], const char** result )
{
    const char *cbName = StringTable->insert(argv[0]);

    if (isEnabled())
    {
        if(isMethod(cbName))
        {
            // This component can handle the given method
            *result = Con::execute( this, argc, argv, true );
            return true;
        }
        else if( getComponentCount() > 0 )
        {
            // Need to try the component's children
            bool handled = false;
            VectorPtr<SimComponent *>&componentList = lockComponentList();
            for( SimComponentIterator nItr = (componentList.end()-1);  nItr >= componentList.begin(); nItr-- )
            {
                argv[0] = cbName;

                SimComponent *pComponent = (*nItr);
                AssertFatal( pComponent, "SimComponent::callMethodOnComponents - NULL component in list!" );

                // Call on children
                handled = pComponent->callMethodOnComponents( argc, argv, result );
                if (handled)
                    break;
            }

            unlockComponentList();

            if (handled)
                return true;
        }
    }

    return false;
}