/*************************************************************************
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.

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

package com.novell.nds.dirxml.driver.skeleton;

import com.novell.nds.dirxml.driver.*;
import com.novell.xml.dom.*;
import org.w3c.dom.*;

/**
 * A basic skeleton for implementing a <code>DriverShim</code>.
 * <p>
 * <code>com.novell.nds.dirxml.driver.DriverShim</code> defines a top-level interface for starting and
 * stopping an application shim.
 * <p>
 * A <code>DriverShim</code> must implement a constructor which takes no parameters
 * in order for the driver infrastructure to instantiate an instance of it.
 * <p>
 * Note that the skeleton driver makes no use of .ini files or any information outside of that
 * supplied through the initialization data supplied to the shim <code>init()</code> methods.
 * In general it is inappropriate for a driver to store configuration information outside of NDS
 * where it cannot be remotely configured using ConsoleOne or other remote configuration utility.
 * <p>
 * In addition it is unwise to have static mutable class data, since that prevents multiple instances
 * of the driver from functioning independently.
 *
 * @version 	2.0 28Jun2000
 */
public class SkeletonDriverShim
	extends CommonImpl
	implements DriverShim
{
	/**
	 * Object implementing <code>com.novell.nds.dirxml.driver.SubscriptionShim</code>, which is
	 * supplied to DirXML via the <code>getSubscriptionShim()</code> method.
	 */
	SkeletonSubscriptionShim subscriptionShim = null;
	/**
	 * Object implementing <code>com.novell.nds.dirxml.driver.PublicationShim</code>, which is
	 * supplied to DirXML via the <code>getPublicationShim()</code> method.
	 */
	SkeletonPublicationShim publicationShim = null;
	/**
	 * Contains driver options from the init params passed to <code>init()</code>
	 */
	ShimParams params = null;
	/**
	 * Instance of inner class AuthenticationParams that is initialized by DriverShim.init()
	 * and DriverShim.getSchema() so that all derived classes may share the auth params
	 * if necessary. Note that the actual strings may be null if no auth info was entered
	 * in ConsoleOne.
	 */
	AuthenticationParams authParams = null;

	/**
	 * A Java driver shim must have a constructor which takes no parameters. DirXML
	 * uses this to construct the driver object.
	 */
	public SkeletonDriverShim()
	{
		//set up the Trace object in CommonImpl with the name of this object
		super("SkeletonDriverShim");
	}

	/**
	 * <code>init</code> will be called after a driver is created to allow the driver
	 * to perform any necessary initialization before starting to process events and
	 * commands. Typically it will perform any setup that is common to both the
	 * subscriber and publisher channels.
	 *
	 * @param initParameters XML document that contains the shim initialization	parameters
	 * @return XML document containing status/messages from the init operation
	 */
	public XmlDocument init(XmlDocument initParameters )
	{
		try
		{
			tracer.trace("init");
			//create an output document for returning status to DirXML
			Element output = createOutputDocument();
			//setup the shared authentication information
			authParams = getAuthenticationParams(initParameters.getDocumentNS());
			//if we don't have any authentication parameters, report a warning. This
			//is intended to serve as an example of how to report a warning or an error. A real
			//driver may or may not need to information in the authentication parameters.
			if (authParams.authenticationId == null &&
				authParams.authenticationContext == null &&
				authParams.applicationPassword == null)
			{
				//a real driver would probably want to report a fatal error if required
				//parameters are not supplied
				addStatusElement(output,STATUS_WARNING,"No authentication information",null);
			}
			//get any non-authentication options from the init document
			params = getShimParams(initParameters.getDocumentNS(),"driver",DRIVER_PARAMS);
			//create the objects that do the real work
			subscriptionShim = new SkeletonSubscriptionShim(authParams);
			publicationShim = new SkeletonPublicationShim(authParams);
			//if we didn't already add a status element, add a success
			if (output.getElementsByTagNameNS(null, "status").item(0) == null)
			{
				addStatusElement(output,STATUS_SUCCESS,null,null);
			}
			//return the status document
			return	new XmlDocument(output.getOwnerDocument());
		} catch (Throwable t)
		{
			//something bad happened...
			return	createStatusDocument(STATUS_FATAL,t.getMessage());
		}
	}

	/**
	 * <code>shutdownShim</code> indicates to the DriverShim that
	 * the driver is being terminated.
	 *
	 * @param initParameters XML document that may contain description of reason for shutdown
	 * @return XML document containing status/messages from shutdown operation
	 */
	public XmlDocument shutdown(XmlDocument reason)
	{
		tracer.trace("shutdown");
		//create an output document so the subscriber can write its state info
		Element output = createOutputDocument();
		subscriptionShim.setState(output);
		// shutdown whatever needs shutting down
		// which will always include telling the publication shim to return control
		// back to the caller
		publicationShim.stop();
		//add a successful status
		addStatusElement(output,STATUS_SUCCESS,null,null);
		//return the status and state to DirXML
		return	new XmlDocument(output.getOwnerDocument());
	}

	/**
	 * <code>getSubscriptionShim</code> gets an implementation of SubscriptionShim
	 * that can be used to process commands on behalf of DirXML.
	 *
	 * @return an instance of  SubscriptionShim that can be used to process
	 * commands on behalf of the DirXML.
	 */
	public SubscriptionShim getSubscriptionShim()
	{
		tracer.trace("getSubscriptionShim");
		return subscriptionShim;
	}

	/**
	 * <code>getPublicationShim</code> gets an implementation of PublicationShim
	 * that can be invoked by NDS.
	  *
	 * @return an instance of PublicationShim that can be invoked by DirXML.
	 */
	public PublicationShim getPublicationShim()
	{
		tracer.trace("getPublicationShim");
		return publicationShim;
	}

	/**
	 * <code>getSchema</code> returns a representation of the application schema data encoded in XML.
	 * <p>
	 * This will be called only when the driver is not running. In other words, if this method is
	 * called init()/shutdown() will not be called for the current instance of the DriverShim.
	 *
	 * @param initParameters XML document containing the driver shim initialization parameters as
	 * well as the subscription shim and publication shim initialization parameters.
	 * @return XML document containing the application schema data, or an error status return.
	 */
	public XmlDocument getSchema(XmlDocument initParameters)
	{
		//setup the shared authentication information
		authParams = getAuthenticationParams(initParameters.getDocumentNS());
		//a driver that supports a real application would do whatever is necessary to
		//create an XDS schema description document and return it. For example, it might
		//create an instance of the Subscriber object and query the application schema.
		//If the application has an invariant schema, the driver might just have an embedded XML document
		//describing the schema in XDS terms. This embedded document could then be returned to DirXML
		//wrapped by an XmlDocument object.
		//
		//However, since we are just a skeleton...
		Element output = createOutputDocument();
		Element schemaDef = output.getOwnerDocument().createElementNS(null,"schema-def");
		output.appendChild(schemaDef);
		schemaDef.setAttributeNS(null,"hierarchical","false");
		return	new XmlDocument(output.getOwnerDocument());
	}

	/**
	 * Table of parameters that this driver shim wants to get from the &lt;driver-options> element
	 * of the init-params.
	 * <p>
	 * This is illustrative, of course, an actual driver would want parameters specific to its
	 * functionality.
	 */
	private static final ShimParamDesc[] DRIVER_PARAMS =
	{
		new ShimParamDesc("option-1",ShimParamDesc.STRING_TYPE,false),
		new ShimParamDesc("option-2",ShimParamDesc.INT_TYPE,false),
	};

}
