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;
}
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;
}
TEST(MoreAdvancedComponent, MoreAdvancedComponent)
{
   // Create component instances and compose them.
   SimComponent *parentComponent = new SimComponent();
   SimpleComponent *simpleComponent = new SimpleComponent();
   MoreAdvancedComponent *moreAdvComponent = new MoreAdvancedComponent();
   // CodeReview note that the interface pointer isn't initialized in a ctor
   //  on the components, so it's bad memory against which you might
   //  be checking in testDependentInterface [3/3/2007 justind]
   parentComponent->addComponent( simpleComponent );
   parentComponent->addComponent( moreAdvComponent );

   simpleComponent->registerObject();
   moreAdvComponent->registerObject();

   // Put a break-point here, follow the onAdd call, and observe the order in
   // which the SimComponent::onAdd function executes. You will see the interfaces
   // get cached, and the dependent interface query being made.
   parentComponent->registerObject();

   // If the MoreAdvancedComponent found an interface, than the parentComponent
   // should have returned true, from onAdd, and should therefore be registered
   // properly with the Sim
   EXPECT_TRUE( parentComponent->isProperlyAdded() )
      << "Parent component not properly added!";

   // Now lets test the interface. You can step through this, as well.
   EXPECT_TRUE( moreAdvComponent->testDependentInterface() )
      << "Dependent interface test failed.";

   // CodeReview is there a reason we can't just delete the parentComponent here? [3/3/2007 justind]
   //
   // Clean up
   parentComponent->removeComponent( simpleComponent );
   parentComponent->removeComponent( moreAdvComponent );

   parentComponent->deleteObject();
   moreAdvComponent->deleteObject();
   simpleComponent->deleteObject();
};