#ifndef _CDEV_ELEMENT_DEFINITION_H_
#define _CDEV_ELEMENT_DEFINITION_H_

#ifndef _CDEV_DIRECTORY_TABLE_H_
	#error "You must include cdevDirectoryTable.h to load cdevElementDefinition.h"
#endif
	
#include <stdio.h>
#include <string.h>

// *****************************************************************************
// * class cdevElementDefinition :
// *	This class is used to store the information that describes the contents
// *	of a single element of a CDEV DDL class definition (verb, attribute,
// *	or message.
// *
// *	This class maintains a variety of internal data items for the following
// *	purposes...
// *
// *	name        - This is the name of the verb, attribute, or message that 
// *                  is represented by this element definition.
// *	service     - This is the service that this element direct the request 
// *                  to.
// *	serviceData - These are the values that will be palcded in the tags
// *                  that were specified in the service definition.
// *	nItems      - This is the number of tagged data items that were 
// *                  specified in the serviceData.
// *    next        - This is the next element item in the list.  Lists of 
// *                  elements are maintained in the cdevClassDefinition objects
// *****************************************************************************
class cdevElementDefinition 
{
private:
	cdevElementDefinition * next; 
	char                  * name;
	cdevServiceDefinition * service;
	char                 ** serviceData;
	int                     nItems;

public:
	inline cdevElementDefinition  ( cdevElementDefinition *def );
	inline cdevElementDefinition  ( char                  * Name = NULL, 
				        cdevServiceDefinition * Service = NULL, 
				        char                 ** ServiceData = NULL, 
				        int                     NItems = 0);
	inline virtual ~cdevElementDefinition ( void );
	inline void asciiDump     ( FILE * fp = stdout);
	inline void asciiDumpList ( FILE * fp = stdout, char * keyword = "UNKNOWN");

	// *********************************************************************
	// * Member access methods.
	// *********************************************************************
	inline char                  * getName        ( void );
	inline cdevServiceDefinition * getService     ( void );
	inline char                 ** getServiceData ( void );
	inline int                     getDataCnt     ( void );           
	inline cdevElementDefinition * getNext        ( void );
	inline void                    setNext        ( cdevElementDefinition * Next );
};



// *****************************************************************************
// * cdevElementDefinition::cdevElementDefinition :
// *	This is the constructor for the cdevElementDefintion class.  This 
// *	constructor copies the contents from a pre-existing 
// *	cdevElementDefinition object, and assumes that the data should be 
// *	deleted by the originating class.
// *****************************************************************************
inline cdevElementDefinition::cdevElementDefinition  ( cdevElementDefinition *def )
	: next         (NULL),
	  name         (def->name),
	  service      (def->service),
	  serviceData  (def->serviceData),
	  nItems       (def->nItems)
	{
	}

// *****************************************************************************
// * cdevElementDefinition::cdevElementDefinition :
// *	This is the constructor for the cdevElementDefinition class and it 
// *	uses literal values that are provoded by the caller.  It assumes that it
// *	it responsible for deleteing these data items when the instance of the
// *	class is deleted.
// *****************************************************************************
inline cdevElementDefinition::cdevElementDefinition  
	( char                  * Name, 
	  cdevServiceDefinition * Service, 
	  char                 ** ServiceData, 
	  int                     NItems)
	: next         (NULL),
	  name         (Name),
	  service      (Service),
	  serviceData  (ServiceData),
	  nItems       (NItems)
	{
	}

// *****************************************************************************
// * cdevElementDefinition::~cdevElementDefinition :
// *	This is the destructor for the cdevElementDefinition class.
// *****************************************************************************
inline cdevElementDefinition::~cdevElementDefinition ( void )
	{
	if(name)             delete name;
	while((--nItems)>=0) delete serviceData[nItems];
	if(serviceData)      delete serviceData;
	}

// *****************************************************************************
// * cdevElementDefinition::asciiDump :
// *	This method will dump the contents of the cdevElementDefinition class
// * 	class to the user specified file pointer.
// *****************************************************************************
inline void cdevElementDefinition::asciiDump ( FILE * fp )
	{
	if(name)
		{
		fprintf(fp, "\t\t%s", name);
		
		if(service)
			{
			fprintf(fp, " %s", service->getName());

			for(int i=0; i<nItems; i++)
				{
				if(i==0) fprintf(fp, " {");
				fprintf(fp, "%s", serviceData[i]);
				if(i<nItems-1) fprintf(fp, ", ");
				else fprintf(fp, "}");
				}
			}
		fprintf(fp, ";\n");
		}
	}

// *****************************************************************************
// * cdevElementDefinition::asciiDumpList :
// *	This method dumps the complete contents of the cdevElementDefinition
// *	list.
// *****************************************************************************
inline void cdevElementDefinition::asciiDumpList (FILE *fp, char * keyword)
	{
	cdevElementDefinition * def        = this;
	int                     nameLen    = 0;
	int                     serviceLen = 0;

	for(def = this; def!=NULL; def = def->next)
		{
		int n = def->name==NULL?0:strlen(def->name);
		int s = def->service==NULL?0:strlen(def->service->getName());
		if(n>nameLen)    nameLen = n;
		if(s>serviceLen) serviceLen = s;
		}
	if(serviceLen)
		{
		fprintf(fp, "\t%s\n\t\t{\n", keyword);			
		for(def = this; def!=NULL; def = def->next)
			{
			if(nameLen>0 && def->service) 
				fprintf(fp, "\t\t%-*s", nameLen, def->name);
			else	fprintf(fp, "\t\t%s", def->name);
			
			if(def->service)
				{
				if(serviceLen>0 && def->nItems) 
					fprintf(fp, " %-*s", serviceLen, def->service->getName());
				else	fprintf(fp, " %s", def->service->getName());

				for(int i=0; i<def->nItems; i++)
					{
					if(i==0) fprintf(fp, " {");
					fprintf(fp, "%s", def->serviceData[i]);
					if(i<def->nItems-1) fprintf(fp, ", ");
					else fprintf(fp, "}");
					}
				}
			fprintf(fp, ";\n");
			}
		fprintf(fp, "\t\t}\n");
		}
	else	{
		int cnt = 0;
		char prefix[25];
		sprintf(prefix, "%s {", keyword);
		fprintf(fp, "\t%s", prefix);
		for(def = this; def!=NULL; def = def->next, cnt++)
			{
			if(def->next)
				{
				fprintf(fp, " %s,", def->name);
				if(cnt==3)
					{
					fprintf(fp, "\n\t%*c", strlen("prefix")+1, 32);
					cnt=-1;
					}
				}
			else fprintf(fp, " %s ", def->name);
			}
		fprintf(fp, "}\n");
		}
	}


// *****************************************************************************
// * cdevElementDefinition::getName :
// *	This method allows the caller to retrieve the name of the element.
// *****************************************************************************
inline char * cdevElementDefinition::getName ( void )
	{
	return name;
	}

// *****************************************************************************
// * cdevElementDefinition::getService :
// *	This method allows the caller to retrieve the service definition
// *****************************************************************************
inline cdevServiceDefinition * cdevElementDefinition::getService ( void )
	{
	return service;
	}

// *****************************************************************************
// * cdevElementDefinition::getServiceData :
// *	This method allows the caller to retrieve the service data.
// *****************************************************************************
inline char ** cdevElementDefinition::getServiceData ( void )
	{
	return serviceData;
	}

// *****************************************************************************
// * cdevElementDefinition::getDataCnt :
// *	This method allows the caller to retrieve the number of strings that
// *	are stored in the serviceData.
// *****************************************************************************
inline int cdevElementDefinition::getDataCnt ( void )
	{
	return nItems;
	}
 
// *****************************************************************************
// * cdevElementDefinition::getNext :
// *	This method allows the caller to retrieve the next element in the list.
// *****************************************************************************
inline cdevElementDefinition * cdevElementDefinition::getNext ( void )
	{
	return next;
	}

// *****************************************************************************
// * cdevElementDefinition::setNext :
// *	This method allows the caller to set the next element in the list.
// *****************************************************************************
inline void cdevElementDefinition::setNext ( cdevElementDefinition * Next )
	{
	next = Next;
	}

#endif /* _CDEV_ELEMENT_DEFINITION_H_ */
