/*************************************************************************
Copyright © 1999-2002 Novell, Inc. All Rights Reserved. 

THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND 
TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE
AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS
THIS WORK. PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS
TO DEVELOPER A ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S
SAMPLE CODE IN ITS PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION
RIGHTS TO MARKET, DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT
OF DEVELOPER'S PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR
DEVELOPER'S CUSTOMERS WITH RESPECT TO THIS CODE.

***************************************************************************/

/*******************************************************************
* Name: CommonImpl.hpp
* Description: Platform independent code, shared code for skeleton
* driver shim implementations
* Tabs: 4
*******************************************************************/

#ifndef	_COMMONIMPL_HPP_
#define	_COMMONIMPL_HPP_

#include	"NativeInterface.h"
#include	"Trace.h"
#include	"dom.h"
#include	"NdsDtd.h"

extern const unicode	MSG_BAD[];

using namespace DOM;

const int STRING_TYPE = 1;
const int INT_TYPE = 2;

//++
/*****************************************************************
Class: CommonImpl
Desc:
	Shared code for implementations of DriverShim, SubscriptionShim,
	and PublicationShim. The implementations contain an instance of
	this class rather than inheriting from it to avoid multiple
	inheritance. For an example of a driver that is implemented 
	using multiple inheritance see the VRTest driver.

Notes:

*****************************************************************/
//--
class CommonImpl
{
public:
	CommonImpl(const char * traceHeader);
	~CommonImpl();

    /**
     * Class for use in storing authentication <init-params> values from the initialization documents
     * passed to DriverShim.init(), SubscriptionShim.init(), or PublicationShim.init()
     * 
	 * These Strings correspond to fields found in ConsoleOne on the DirXML-Driver object
	 * properties dialog, under DirXML, Driver Configuration, Authentication.
	 * 
	 * The fields are intended to be used as follows (but a driver can, of course, use them
	 * in any way appropriate to the driver and its supported application):
	 * 
	 * Authentication ID: Stores the User ID or other ID used for the driver to authenticate or
	 * connect to the application.
	 * 
	 * Authentication context: Stores a server name, IP address, or other information used to
	 * inform the driver to which application instance or server the driver is to connect.
	 * 
	 * Application password: Stores in a secure fashion the application password the driver needs
	 * to authenticate to the application.
     */
	struct AuthenticationParams
	{
		AuthenticationParams(const unicode * id, const unicode * context, const unicode * password);
		~AuthenticationParams();
		//corresponds to "Authentication ID" field
		const unicode * authenticationId;
		//corresponds to "Authentication context" field
		const unicode * authenticationContext;
		//corresponds to "Application Password" field
		const unicode * applicationPassword;
	};

    /**
     * Class used to build an array of options element descriptions
     * for use in getShimOptions().
     * 
     * Each options element is described in terms of element name and
     * how the content should be interpreted.
	 *
	 * paramType may be STRING_TYPE or INT_TYPE
     */
	struct ShimParamDesc
	{
		//Name of shim parameter (element name in init document)
		const unicode * paramName;
		//STRING_TYPE or INT_TYPE
		int				paramType;
		//true if an exception should be thrown if parameter isn't supplied
		bool			required;
	};

    /**
     * Class to store values from a <driver-options>, <subscriber-options>,
     * <publisher-options>, <driver-state>, <subscriber-state>, or <publisher-state>
	 * element from an init document.
     * 
     * Values are keyed by the element name in the options XML, and may
     * be either Strings or ints. This is not the most efficient way to
     * store such things, but it needs to be general to serve as an example
     * for the skeleton driver.
     */
	class ShimParams
	{
	public:
		ShimParams();
		~ShimParams();

		//set a string-type parameter
		void
			putStringParam(const unicode * name, const unicode * value);
		//get a string-type parameter by name (returns 0 if not found)
		const unicode *
			getStringParam(const unicode * name) const;
		//set an int-type parameter
		void
			putIntParam(const unicode * name, int value);
		//get an int-type parameter by name (returns -1 if not found)
		int
			getIntParam(const unicode * name) const;
		//return true if param with passed name is in collection
		bool
			haveParam(const unicode * name) const;
	protected:
		//NOTE: a potentially better method of storing the name-value pairs
		//is with an STL map, but we didn't want to make the skeleton driver
		//depend on STL.
		struct Entry
		{
			Entry();
			~Entry();
			void
				assign(const unicode * name, const unicode * value);
			void
				assign(const unicode * name, int value);
			const unicode * name;
			int				type;
			union
			{
				const unicode * stringValue;
				int				intValue;
			};
		private:
			void
				cleanup();
			//hide so don't inadvertently use
			Entry(const Entry &);
			Entry &
				operator = (const Entry &);
		};
		Entry * table;
		int entryCount;
		int tableSize;
		void
			sizeTable();
		const Entry *
			find(const unicode *) const;
	};

	
	//create an output document with <status level="success"/> element
	XmlDocument *
		createSuccessDocument() const;
	
	//create an output document with a <status> element with passed level and message
	XmlDocument *
		createStatusDocument(int level, const unicode * message) const;

	//add <driver-state>, <subscriber-state>, or <publisher-state> to an input or output document
	Element *
		addState(Element * parent, const unicode * stateName, const unicode * elementName, const unicode * elementValue) const;

	//Get authentication info passed to an init method
	AuthenticationParams *
		getAuthenticationParams(Document * initDocument) const;

	//Get init parameters from <driver-options>, <subscriber-options>, <publisher-options>, <driver-state>,
	//<subscriber-state>, or <publisher-state> (from document passed to init method)
    ShimParams * 
		getShimParams(Document * initDocument, const unicode * shimName, const ShimParamDesc * paramDesc) const;

	//Get the text value of the first text node child of an element.
	static const unicode * 
		getElementValue(Element * element);

	//Return documents:
	//Any object created by the driver must be cleaned up by the driver. Therefore, we must keep track of
	//return documents created by this driver and clean them up when they are no longer needed.

	//Set the document for return from the current interface method (wraps in an XmlDocument).
	XmlDocument *
		setReturnDocument(Document * doc);

	//Set the document for return from the current interface method
	XmlDocument *
		setReturnDocument(XmlDocument * xmlDoc);

	//Get the currently set return document
	XmlDocument *
		getReturnDocument();

	//Get the first element by tag name
	static Element *
		getFirstElementByTagName(Node * root, const unicode * tagName);

	// Instance of com.novell.nds.dirxml.driver.Trace, for use by derived class to output
	// trace messages to DSTrace screen and DirXML-JavaTraceFile specified file.
	// 
	// To cause trace messages to appear on the DSTrace screen set the DirXML-DriverTraceLevel
	// attribute on the driver set object to a value greater than zero. To log trace messages
	// set the DirXML-JavaTraceFile attribute on the driver set object to a filename value.
	Trace * tracer;

	//pointer to NdsDtd structure with unicode versions of the DirXML DTD elements names,
	//attribute names, etc. See NdsDtd.h
	const NdsDtd	* ndsDtd;

private:

	XmlDocument	* returnDocument;

	//helper function for getShimParams
    static void
		extractValues(Element * optionsElement, ShimParams * params, const ShimParamDesc * paramDesc);
};

//class for throwing exceptions with error messages in
//shims
class ShimException
{
public:
	ShimException(const unicode * message);
	ShimException(const ShimException & iVal);
	virtual ~ShimException();

	ShimException &
		operator = (const ShimException & rhs);

	const unicode *
		getMessage() const;

private:
	unicode	* message;
	void
		cleanup();
};


#endif	//#ifndef	_COMMONIMPL_HPP_

