//
// $Id: MetabaseKeyData.cpp,v 1.1 2004/06/01 17:05:20 bakerj Exp $
//
//************************** Property of the MITRE Corporation ***************************//
//
// Copyright (c) 2003 - The MITRE Corporation
//
// This file is part of the Query-based Network Assessment project.
//
// The Query-based Network Assessment is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License.
//
// The Query-based Network Assessment is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with the
// Query-based Network Assessment; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//****************************************************************************************//

#include "MetabaseKeyData.h"

//****************************************************************************************//
//								MetabaseKeyData Class								  //	
//****************************************************************************************//
MetabaseKeyData::MetabaseKeyData(DOMNode *test)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Initialize a new MetabaseKeyData and populate with the node's data
	// -----------------------------------------------------------------------

	string testName;

	//	Validate the test node
	if(test->getNodeType() != DOMNode::ELEMENT_NODE )
	{
		throw ProbeDataException("Error: MetabaseKeyData() Invalid test node specified.");
	}else
	{
		testName = DOMCommon::ToString(test->getNodeName());
		if(testName.compare("metabase_test") != 0)
			throw ProbeDataException("Error: MetabaseKeyData() Invalid test node specified.");
	}

	//	Init the data members
	testId = "";
	key = new TypedData(LITTERAL_TYPE, "");
	identifier = new TypedData(LITTERAL_TYPE, "");
	name = new TypedData(LITTERAL_TYPE, "");
	user_type = "";
	data_type = "";
	data = "";
	msg = "";

	//	Call the parse node function
	ParseNode(test);
}

MetabaseKeyData::MetabaseKeyData()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Initialize a new MetabaseKeyData as an empty object.
	// -----------------------------------------------------------------------
	testId = "";
	key = new TypedData(LITTERAL_TYPE, "");
	identifier = new TypedData(LITTERAL_TYPE, "");
	name = new TypedData(LITTERAL_TYPE, "");
	user_type = "";
	data_type = "";
	data = "";
	msg = "";
}

MetabaseKeyData::~MetabaseKeyData()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Do nothing for now
	// -----------------------------------------------------------------------

}

// ***************************************************************************************	//
//								Public members												//
// ***************************************************************************************	//
void MetabaseKeyData::Write(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *dataDocument)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Create a new metabase_test node and add it to the dataDocument.
	//	
	// -----------------------------------------------------------------------

	//	Create a new test node
	DOMElement *metabase_test = CreateNewTestNode(dataDocument, "metabase_test");

	//	Add the key element - as a STRING_TYPE
	AddChildNode(dataDocument, metabase_test, "key", key->data);

	//	Add the id element - as an INTEGER_TYPE
	if(key->data.compare("") != 0)
		AddChildNode(dataDocument, metabase_test, "id", identifier->data, INTEGER_DATATYPE);

	//	Add the name element - as a STRING_TYPE
	if(identifier->data.compare("") != 0)
		AddChildNode(dataDocument, metabase_test, "name", name->data);

	if((key->data.compare("") != 0) && (identifier->data.compare("") != 0))
	{
		//	Add the user_type element - as a STRING_TYPE
		AddChildNode(dataDocument, metabase_test, "user_type", user_type);

		//	Add the data_type element - as a STRING_TYPE
		AddChildNode(dataDocument, metabase_test, "data_type", data_type);

		//	Add the data element - may be int, string, binary, or float
		AddChildNode(dataDocument, metabase_test, "data", data, DetermineDataType(data));
	}

	//	Add the message element
	AddChildNode(dataDocument, metabase_test, "message", msg);
}

// ***************************************************************************************	//
//								Private members												//
// ***************************************************************************************	//
void MetabaseKeyData::ParseNode(DOMNode *test)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Parse the node gathering all data to popular this MetabaseKeyData
	//	
	// -----------------------------------------------------------------------
	string childName	= "";
	string childOp		= "";
	
	DOMNode *metabaseChild;
	DOMNodeList *metabaseChildList;

	///////////////////////////////////////////////////////////////////////////
	//	Get the test id
	///////////////////////////////////////////////////////////////////////////
	testId = DOMCommon::GetAttributeByName(test, "id");
	if(testId.compare("") == 0)
		throw ProbeDataException("Error: Unable to find the 'id' attribute for a windows metabase test.");	


	///////////////////////////////////////////////////////////////////////////
	//	Gather the data needed to call the probe
	///////////////////////////////////////////////////////////////////////////
	//	get a list of the child nodes and their values
	metabaseChildList = test->getChildNodes();
	unsigned int index = 0;
	while(index < metabaseChildList->getLength())
	{
		metabaseChild = metabaseChildList->item(index);

		//	only concerned with ELEMENT_NODEs
		if (metabaseChild->getNodeType() == DOMNode::ELEMENT_NODE)
		{
			//	get the name of the child
			childName = DOMCommon::ToString(metabaseChild->getNodeName());
			
			//	Get the key value	
			if(strncmp(childName.c_str(), "key", 3)==0)
			{
				key->data = DOMCommon::GetDataNodeValue(metabaseChild);

				//	Get the operation attribute
				childOp = DOMCommon::GetAttributeByName(metabaseChild, "operator");

				if(childOp.compare("pattern match") == 0)
					key->type = PATTERN_MATCH_TYPE;
				else
					key->type = LITTERAL_TYPE;
				
			//	Get the id value
			}else if(strncmp(childName.c_str(), "id", 2)==0)
			{
				identifier->data = DOMCommon::GetDataNodeValue(metabaseChild);

				//	Get the operation attribute
				childOp = DOMCommon::GetAttributeByName(metabaseChild, "operator");

				if(childOp.compare("pattern match") == 0)
					identifier->type = PATTERN_MATCH_TYPE;
				else
					identifier->type = LITTERAL_TYPE;
			
			//	Get the name value
			}else if(strncmp(childName.c_str(), "name", 4)==0)
			{
				name->data = DOMCommon::GetDataNodeValue(metabaseChild);

				//	Get the operation attribute
				childOp = DOMCommon::GetAttributeByName(metabaseChild, "operator");

				if(childOp.compare("pattern match") == 0)
					name->type = PATTERN_MATCH_TYPE;
				else
					name->type = LITTERAL_TYPE;
			}
		}
		index ++;
	}
}