void CStateTable::remove( const CNode &node )
	{
		/* remove self from path map */
		const string &path = node.get_path();
		if( m_nodes.count( path ) != 1 )
		{
			INTEGRA_TRACE_ERROR << "missing key in state table: " << path;
		}
		else
		{
			m_nodes.erase( path );
		}

		/* remove self from id map */
		internal_id id = node.get_id();
		if( m_nodes_by_id.count( id ) != 1 )
		{
			INTEGRA_TRACE_ERROR << "missing key in state table: " << id;
		}
		else
		{
			m_nodes_by_id.erase( id );
		}

		/* remove node endpoints */
		const node_endpoint_map node_endpoints = node.get_node_endpoints();
		for( node_endpoint_map::const_iterator i = node_endpoints.begin(); i != node_endpoints.end(); i++ )
		{
			const INodeEndpoint *node_endpoint = i->second;
			const string &path = node_endpoint->get_path();
			if( m_node_endpoints.count( path ) != 1 )
			{
				INTEGRA_TRACE_ERROR << "missing key in state table: " << path;
			}
			else
			{
				m_node_endpoints.erase( path );
			}
		}

		/* remove child nodes */
		const node_map &children = node.get_children();
		for( node_map::const_iterator i = children.begin(); i != children.end(); i++ )
		{
			remove( *CNode::downcast_writable( i->second ) );
		}
	}
	void CContainerLogic::activate_tree( CServer &server, const CNode &node, bool activate, path_list &activated_nodes )
	{
		/*
		sets 'active' endpoint on any descendants that are not containers
		If any node in ancestor chain are not active, sets descendants to not active
		If all node in ancestor chain are active, sets descendants to active

		Additionally, the function pushes 'activated_nodes' - a list of pointers to 
		nodes which were activated by the function.
		The caller can use this list to perform additional logic
		*/

		const INodeEndpoint *active_endpoint = node.get_node_endpoint( endpoint_active );

		if( dynamic_cast< CContainerLogic * > ( &node.get_logic() ) )
		{
			/* if node is a container, update 'activate' according to it's active flag */
			assert( active_endpoint );
			activate &= ( ( int ) *active_endpoint->get_value() != 0 );
		}
		else
		{
			/* if node is not a container, update it's active flag (if it has one) according to 'activate' */
			if( active_endpoint )
			{
				CIntegerValue value( activate ? 1 : 0 );

				if( !active_endpoint->get_value()->is_equal( value ) )
				{
					server.process_command( ISetCommand::create( active_endpoint->get_path(), value ), CCommandSource::SYSTEM );

					if( activate )
					{
						activated_nodes.push_back( node.get_path() );
					}
				}
			}
		}

		const node_map &children = node.get_children();
		for( node_map::const_iterator i = children.begin(); i != children.end(); i++ )
		{
			activate_tree( server, *CNode::downcast( i->second ), activate, activated_nodes );
		}
	}