Example #1
0
/*************************************************************
* @brief Invoke the list of callbacks matching the doctype of the incoming message.
*
* @param pIncomingMsg	The SML message that should be passed to the callbacks.
* @returns The response message (or NULL if there is no response from any callback).
*************************************************************/
ElementXML* Connection::InvokeCallbacks(ElementXML *pIncomingMsg)
{
	ClearError() ;

	MessageSML *pIncomingSML = (MessageSML*)pIncomingMsg ; // MessageSML is a soarxml::ElementXML, not sml::ElementXML

	// Check that we were passed a valid message.
	if (pIncomingMsg == NULL)
	{
		SetError(Error::kInvalidArgument) ;
		return NULL ;
	}

	// Retrieve the type of this message
	char const* pType = pIncomingSML->GetDocType() ;

	// Check that this message has a valid doc type (all valid SML do)
	if (pType == NULL)
	{
		SetError(Error::kNoDocType) ;
		return NULL ;
	}

	// Decide if this message is a "call" which requires a "response"
	bool isIncomingCall = pIncomingSML->IsCall() ;

	// See if we have a list of callbacks for this type
	CallbackList* pList = GetCallbackList(pType) ;

	// Nobody was interested in this type of message, so we're done.
	if (pList == NULL)
	{
		return NULL ;
	}

	CallbackListIter iter = pList->begin() ;

	// Walk the list of callbacks in turn until we reach
	// the end or one returns a message.
	while (iter != pList->end())
	{
		Callback* pCallback = *iter ;
		iter++ ;

		ElementXML* pResponse = pCallback->Invoke(pIncomingMsg) ;

		if (pResponse != NULL)
		{
			if (isIncomingCall)
				return pResponse ;

			// This callback was not for a call and should not return a result.
			// Delete the result and ignore it.
			pResponse->ReleaseRefOnHandle() ;
			pResponse = NULL ;
		}
	}

	// If this is a call, we must respond
	if (isIncomingCall)
		SetError(Error::kNoResponseToCall) ;

	// Nobody returned a response
	return NULL ;
}