// $Id: CInterXmlDB.cc,v 1.10 2003/05/30 05:27:14 ta_muto Exp $

#include <xupdate/CInterXmlDB.h>

wax::CInterXmlDB::CInterXmlDB()
{
	connection = NULL;
	file = NULL;
	targetDoc = NULL;
	macro = NULL;
}

wax::CInterXmlDB::~CInterXmlDB()
{
	if(connection != NULL)	xmlFree(connection);
	if(file != NULL)	delete file;
	if(targetDoc != NULL)	xmlFreeDoc(targetDoc);
	if(macro != NULL)	delete macro;
}

bool wax::CInterXmlDB::open(const xmlChar* connect)
{
	connection = xmlStrdup(connect);
	file = new CFileLiteracy(connection);
	targetDoc = CXmlLibs::read(file);
	if(targetDoc == NULL)	return false;
	macro = new CXPathMacro(targetDoc);
	return true;
}

void wax::CInterXmlDB::registerVariable(const xmlChar* name, const xmlChar* value)
{
	if(macro != NULL) {
		macro->registerVariable(name, value);
	}
}

bool wax::CInterXmlDB::flush()
{
#if LE==1
	if(xmlDocDump(file->getFILE(), targetDoc) == -1) {
#else
	if(xmlDocFormatDump(file->getFILE(), targetDoc, 1) == -1) {
#endif
		IError::message(ERR_FAILEDSAVE);
		file->unlock();
		return false;
	}
	file->flush();
	return true;
}

void wax::CInterXmlDB::close()
{
	file->unlock();
}

bool wax::CInterXmlDB::isMatch(const xmlChar* connect)
{
	if(!xmlStrcmp(connect, connection))	return true;
	return false;
}

bool wax::CInterXmlDB::select(const xmlChar* xpath)
{
	if(macro == NULL) {
		IError::message(ERR_OUTOFMEMORY, LOCATION);
		return false;
	}
	if(macro->evaluate(xpath) == false) {
		IError::message(ERR_XPATH);
		return false;
	}
	return true;
}

bool wax::CInterXmlDB::insertAfter(xmlDocPtr doc)
{
	if(doc == NULL || doc->children == NULL) {
		IError::message(ERR_WRITEDATA);
		return false;
	}
	xmlNodePtr selectedNode = macro->getNode(0);
	if(selectedNode == NULL) {
		IError::message(ERR_FOUNDNODESET);
		return false;
	}
	xmlAddNextSibling(selectedNode, doc->children);
	return true;
}

bool wax::CInterXmlDB::insertBefore(xmlDocPtr doc)
{
	if(doc == NULL || doc->children == NULL) {
		IError::message(ERR_WRITEDATA);
		return false;
	}
	xmlNodePtr selectedNode = macro->getNode(0);
	if(selectedNode == NULL) {
		IError::message(ERR_FOUNDNODESET);
		return false;
	}
	xmlAddPrevSibling(selectedNode, doc->children);
	return true;
}

bool wax::CInterXmlDB::append(xmlDocPtr doc, const xmlChar* child)
{
	if(doc == NULL || doc->children == NULL) {
		IError::message(ERR_WRITEDATA);
		return false;
	}
	xmlNodePtr selectedNode = macro->getNode(0);
	if(selectedNode == NULL) {
		IError::message(ERR_FOUNDNODESET);
		return false;
	}
	if(child == NULL || !xmlStrcmp(child, (const xmlChar*) "last()")) {
		if(selectedNode->last == NULL) {
			xmlAddChild(selectedNode, xmlCopyNode(doc->children, 1));
		} else {
			xmlAddNextSibling(selectedNode->last, doc->children);
		}
	} else {
		xmlNodePtr cur = selectedNode->children;
		if(cur == NULL) {
			xmlAddChild(selectedNode, xmlCopyNode(doc->children, 1));
		} else {
			int pos = atoi((const char*) child);
			for(int i = 0; i < pos; i++) {
				if(cur == NULL) {
					cur = selectedNode->last;
					break;
				}
				cur = cur->next;
			}
			xmlAddNextSibling(cur, doc->children);
		}
	}
	return true;
}

bool wax::CInterXmlDB::rename(const xmlChar* name)
{
	xmlNodePtr selectedNode = macro->getNode(0);
	if(selectedNode == NULL) {
		IError::message(ERR_FOUNDNODESET);
		return false;
	}
	xmlNodeSetName(selectedNode, name);
	return true;
}

bool wax::CInterXmlDB::updateContent(xmlDocPtr doc)
{
	if(doc == NULL || doc->children == NULL) {
		IError::message(ERR_WRITEDATA);
		return false;
	}
	xmlNodePtr selectedNode = macro->getNode(0);
	if(selectedNode == NULL) {
		IError::message(ERR_FOUNDNODESET);
		return false;
	}
	xmlNodeSetContent(selectedNode, xmlNodeGetContent(doc->children));
	return true;
}

bool wax::CInterXmlDB::remove()
{
	xmlNodePtr selectedNode = macro->getNode(0);
	if(selectedNode == NULL) {
		IError::message(ERR_FOUNDNODESET);
		return false;
	}
	xmlUnlinkNode(selectedNode);
	xmlFreeNode(selectedNode);
	return true;
}
