static bool AddWmeChildrenToXML( AgentSML* pAgentSML, wme* pRoot, soarxml::ElementXML* pTagResult, std::list< wme* >& traversedList )
{
	if (!pRoot || !pTagResult)
		return false ;

    for (wme* w = pRoot->value->id.input_wmes; w != NIL; w = w->next)
	{
		TagWme* pTagWme = OutputListener::CreateTagWme( pAgentSML, w ) ;

#ifdef _DEBUG
		// Set a break point in here to look at the message as a string
		char *pStr = pTagWme->GenerateXMLString(true) ;
		pTagWme->DeleteString(pStr) ;
#endif

		// Add this wme into the result
		pTagResult->AddChild(pTagWme) ;

		// If this is an identifier then add all of its children too
		if ( w->value->sc.common_symbol_info.symbol_type == IDENTIFIER_SYMBOL_TYPE )
		{	
			if ( std::find( traversedList.begin(), traversedList.end(), w ) == traversedList.end() )
			{
				traversedList.push_back( w );
				AddWmeChildrenToXML( pAgentSML, w, pTagResult, traversedList );
			}
		}
	}

	return true ;
}
示例#2
0
TagWme* OutputListener::CreateTagWme(AgentSML* pAgent, wme* wme)
{
    // Create the wme tag
    TagWme* pTag = new TagWme() ;
    
    // Look up the type of value this is
    char const* pValueType = AgentSML::GetValueType(wme->value->symbol_type) ;
    
    // For additions we send everything
    pTag->SetIdentifier(wme->id->to_string(true));
    pTag->SetAttribute(wme->attr->to_string());
    pTag->SetValue(wme->value->to_string(), pValueType) ;
    
    int64_t clientTimetag = pAgent->GetClientTimetag(wme->timetag);
    if (clientTimetag < 0)
    {
        // valid client timetag
        pTag->SetTimeTag(clientTimetag) ;
    }
    else
    {
        pTag->SetTimeTag(wme->timetag) ;
    }
    
    pTag->SetActionAdd() ;
    
    return pTag ;
}
示例#3
0
void DeltaList::RemoveWME(long long timeTag)
{
// BADBAD: We should scan the existing list of tags and if we are adding this value
// just delete that tag and don't add anything to the delta list.
// (This will happen if we change a value twice within a commit cycle).
// We probably shouldn't do this if the object being removed is an identifier
// as we might leave pending adds that are children of the object.
// (Then again, that might be ok as presumably those adds would fail when we
//  got to the kernel, possibly saving a bunch of time in the matcher).

	// Create the wme tag
	TagWme* pTag = new TagWme() ;

	// For removes, we just use the time tag
	pTag->SetTimeTag(timeTag) ;
	pTag->SetActionRemove() ;

	m_DeltaList.push_back(pTag) ;	
}
示例#4
0
void DeltaList::AddWME(WMElement* pWME)
{
	// Create the wme tag
	TagWme* pTag = new TagWme() ;

	// For adds we send everything
	pTag->SetIdentifier(pWME->GetIdentifier()->GetIdentifierSymbol()) ;
	pTag->SetAttribute(pWME->GetAttribute()) ;
	std::string temp;
	pTag->SetValue(pWME->GetValueAsString(temp), pWME->GetValueType()) ;
	pTag->SetTimeTag(pWME->GetTimeTag()) ;
	pTag->SetActionAdd() ;

	m_DeltaList.push_back(pTag) ;	
}
示例#5
0
void OutputListener::SendOutput(smlWorkingMemoryEventId eventId, AgentSML* pAgentSML, int /*outputMode*/, io_wme* io_wmelist)
{
    if (eventId != smlEVENT_OUTPUT_PHASE_CALLBACK)
    {
        return ;
    }
    
    // Get the first listener for this event (or return if there are none)
    ConnectionListIter connectionIter ;
    if (!EventManager<smlWorkingMemoryEventId>::GetBegin(eventId, &connectionIter))
    {
        return ;
    }
    
    // We need the first connection for when we're building the message.  Perhaps this is a sign that
    // we shouldn't have rolled these methods into Connection.
    Connection* pConnection = *connectionIter ;
    
    // Build the SML message we're doing to send.
    soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Output) ;
    
    // Add the agent parameter and as a side-effect, get a pointer to the <command> tag.  This is an optimization.
    ElementXML_Handle hCommand = pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamAgent, pAgentSML->GetName()) ;
    soarxml::ElementXML command(hCommand) ;
    
    // We are passed a list of all wmes in the transitive closure (TC) of the output link.
    // We need to decide which of these we've already seen before, so we can just send the
    // changes over to the client (rather than sending the entire TC each time).
    
    // Reset everything in the current list of tags to "not in use".  After we've processed all wmes,
    // any still in this state have been removed.
    for (OutputTimeTagIter iter = m_TimeTags.begin() ; iter != m_TimeTags.end() ; iter++)
    {
        iter->second = false ;
    }
    
    // Start with the output link itself
    // The kernel seems to only output this itself during link initialization
    // and we might be connecting up after that.  Including it twice will not hurt on the client side.
    output_link* ol = pAgentSML->GetSoarAgent()->existing_output_links ;    // This is technically a list but we only support one output link
    TagWme* pOutputLinkWme = OutputListener::CreateTagWme(pAgentSML, ol->link_wme) ;
    command.AddChild(pOutputLinkWme) ;
    
    for (io_wme* wme = io_wmelist ; wme != NIL ; wme = wme->next)
    {
        // Build the list of WME changes
        uint64_t timeTag = wme->timetag ;
        
        // See if we've already sent this wme to the client
        OutputTimeTagIter iter = m_TimeTags.find(timeTag) ;
        
        if (iter != m_TimeTags.end())
        {
            // This is a time tag we've already sent over, so mark it as still being in use
            iter->second = true ;
            continue ;
        }
        
        // If we reach here we need to send the wme to the client and add it to the list
        // of tags currently in use.
        m_TimeTags[timeTag] = true ;
        
        // Create the wme tag
        TagWme* pTag = CreateTagIOWme(pAgentSML, wme) ;
        
        // Add it as a child of the command tag
        command.AddChild(pTag) ;
    }
    
    // At this point we check the list of time tags and any which are not marked as "in use" must
    // have been deleted, so we need to send them over to the client as deletions.
    for (OutputTimeTagIter iter = m_TimeTags.begin() ; iter != m_TimeTags.end() ;)
    {
        // Ignore time tags that are still in use.
        if (iter->second == true)
        {
            // We have to do manual iteration because we're deleting elements
            // as we go and that invalidates iterators if we're not careful.
            iter++ ;
            continue ;
        }
        
        uint64_t timeTag = iter->first ;
        
        // Create the wme tag
        TagWme* pTag = new TagWme() ;
        
        // For deletions we just send the time tag
        pTag->SetTimeTag(static_cast<int64_t>(timeTag)) ;
        pTag->SetActionRemove() ;
        
        // Add it as a child of the command tag
        command.AddChild(pTag) ;
        
        // Delete the entry from the time tag map
        m_TimeTags.erase(iter++);
    }
    
    // This is important.  We are working with a subpart of pMsg.
    // If we retain ownership of the handle and delete the object
    // it will release the handle...deleting part of our message.
    command.Detach() ;
    
    smlWorkingMemoryEventId eventID = smlEVENT_OUTPUT_PHASE_CALLBACK ;
    
#ifdef _DEBUG
    // Convert the XML to a string so we can look at it in the debugger
    char* pStr = pMsg->GenerateXMLString(true) ;
#endif
    
    // Send the message out
    AnalyzeXML response ;
    SendEvent(pAgentSML, pConnection, pMsg, &response, connectionIter, GetEnd(eventID)) ;
    
#ifdef _DEBUG
    pMsg->DeleteString(pStr) ;
#endif
    
    // Clean up
    delete pMsg ;
}