//
// See the file LICENSE for redistribution information.
//
// Copyright (c) 2002-2003
//	Sleepycat Software.  All rights reserved.
//
// $Id: XmlValue.hpp,v 1.31 2003/09/29 15:02:54 merrells Exp $
//

#ifndef __XMLVALUE_HPP
#define	__XMLVALUE_HPP

#include "XmlPortability.hpp"
#include "DbXmlFwd.hpp"
#include <string>

#if defined(DBXML_DOM_XERCES2)
#include <xercesc/dom/DOM.hpp>

#if !defined(XERCES_CPP_NAMESPACE_QUALIFIER)
 #define XERCES_CPP_NAMESPACE_QUALIFIER
#endif
#endif

namespace DbXml
{

class Value;
class QueryContext;

class DBXML_EXPORT XmlValue
{
public:
	enum Type
	{
	    NONE,  ///< None
	    STRING,  ///< String
	    NUMBER,  ///< Number
	    BOOLEAN,  ///< Boolean
	    DOCUMENT,  ///< Document
	    NODE,  ///< Node
	    VARIABLE,  ///< Variable
	    BINARY ///< Binary
	};

	XmlValue();
	XmlValue(const std::string &v);
	XmlValue(const char *v);
	XmlValue(double v);
	XmlValue(bool v);
	XmlValue(const XmlDocument &v);
#if defined(DBXML_DOM_XERCES2)
	XmlValue(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode &n, const XmlDocument *document, QueryContext *context = 0);
#endif

	XmlValue(Type type, const std::string &v);
	XmlValue(Type type, const Dbt &dbt);
	virtual ~XmlValue();
	XmlValue(const XmlValue &);
	XmlValue &operator=(const XmlValue &);

	/// What type is the Value.
	Type getType(const XmlQueryContext *context = 0) const;

	/// Is the value a Number.
	bool isNumber(const XmlQueryContext *context = 0) const;
	/// Is the value a String.
	bool isString(const XmlQueryContext *context = 0) const;
	/// Is the value a Boolean.
	bool isBoolean(const XmlQueryContext *context = 0) const;
	/// Is the value a Node
	bool isNode(const XmlQueryContext *context = 0) const;
	/// Is the value a Document.
	bool isDocument(const XmlQueryContext *context = 0) const;
	/// Is the value a Variable
	bool isVariable(const XmlQueryContext *context = 0) const;
	/// Does the value have no value.
	bool isNull() const;

	/// Return the value as a Number.
	double asNumber(const XmlQueryContext *context = 0) const;
	/// Return the value as a String.
	std::string asString(const XmlQueryContext *context = 0) const;
	/// Return the value as a Boolean.
	bool asBoolean(const XmlQueryContext *context = 0) const;
#if defined(DBXML_DOM_XERCES2)
	/// Return the value as a Node
	XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *asNode(const XmlQueryContext *context = 0) const;
#endif
	/// Return the value as a Document.
	XmlDocument asDocument(const XmlQueryContext *context = 0) const;

	/// Compare two values for equality.
	bool equals(const XmlValue &v, const XmlQueryContext *context = 0) const;

	// XPath functions for Strings
	static XmlValue startsWith(const XmlQueryContext *context, const XmlValue &a, const XmlValue &b);
	static XmlValue contains(const XmlQueryContext *context, const XmlValue &a, const XmlValue &b);
	static XmlValue string(const XmlQueryContext *context, const XmlValue &a);
	static XmlValue substringBefore(const XmlQueryContext *context, const XmlValue &a, const XmlValue &b);
	static XmlValue substringAfter(const XmlQueryContext *context, const XmlValue &a, const XmlValue &b);
	static XmlValue substring(const XmlQueryContext *context, const XmlValue &a, const XmlValue &b);
	static XmlValue substring(const XmlQueryContext *context, const XmlValue &a, const XmlValue &b, const XmlValue &c);
	static XmlValue stringLength(const XmlQueryContext *context, const XmlValue &a);
	static XmlValue translate(const XmlQueryContext *context, const XmlValue &a, const XmlValue &b, const XmlValue &c);
	static XmlValue normalizeSpace(const XmlQueryContext *context, const XmlValue &a);

	// XPath functions for Booleans
	static XmlValue boolean(const XmlQueryContext *context, const XmlValue &a);
	static XmlValue booleanNot(const XmlQueryContext *context, const XmlValue &a);
	static XmlValue booleanTrue(const XmlQueryContext *context);
	static XmlValue booleanFalse(const XmlQueryContext *context);

	// XPath functions for Numbers
	static XmlValue number(const XmlQueryContext *context, const XmlValue &a);
	static XmlValue floor(const XmlQueryContext *context, const XmlValue &a);
	static XmlValue ceiling(const XmlQueryContext *context, const XmlValue &a);
	static XmlValue round(const XmlQueryContext *context, const XmlValue &a);

	// private
	operator Value *() const
	{
		return value_;
	}
private:
	Value *value_;
};

}

#endif
