Files
cdev-1.7.2n/include/cdevClassDefinition.h
2022-12-13 12:44:04 +01:00

698 lines
25 KiB
C++

#ifndef _CDEV_CLASS_DEFINITION_H_
#define _CDEV_CLASS_DEFINITION_H_
#ifndef _CDEV_DIRECTORY_TABLE_H_
#error "You must include cdevDirectoryTable.h to load cdevClassDefinition.h"
#endif
// *****************************************************************************
// * class cdevClassDefinition :
// * This class stores the definition of a single CDEV DDL class and all
// * of its associated verbs, attributes and messages.
// *
// * This class maintains a variety of internal data items for the following
// * purposes...
// *
// * directory - This is the cdevDirectoryTable that the class definition
// * is a member of...
// *
// * name - This is the name of the class as defined in the CDEV DDL
// * file.
// *
// * verbs - This is a list of cdevElementDefinitions that identify
// * each verb that was defined within the class definition.
// *
// * attributes - This is a list of cdevElementDefinitions that identify
// * each attribute that was defined within the class
// * definition.
// *
// * messages - This is a list of cdevElementDefinitions that identify
// * each messages that was defined within the class defintion.
// *
// * parent - This is the class definition for the class that this one
// * inherited from - if any.
// *
// * deviceHead - This is a list of device definitions for all devices that
// * deviceTail were created from this class.
// *
// * redirector - This is a table of all complete messages that this class
// * will support. This table is only generated if devices are
// * instanciated from the class - and it includes the message
// * contents from all parent classes.
// *
// * next - This is the next class definition that occurs... This list
// * is maintained in the cdevDirectoryTable object.
// *****************************************************************************
class cdevClassDefinition
{
private:
cdevDirectoryTable & directory;
cdevClassDefinition * next;
char * name;
cdevElementDefinition * verbs;
cdevElementDefinition * attributes;
cdevElementDefinition * messages;
cdevClassDefinition * parent;
cdevDeviceDefinition * deviceHead;
cdevDeviceDefinition * deviceTail;
StringHash redirector;
public:
inline cdevClassDefinition(cdevDirectoryTable &Master,
char *Name = NULL,
cdevClassDefinition *Parent = NULL,
cdevElementDefinition *Verbs = NULL,
cdevElementDefinition *Attributes = NULL,
cdevElementDefinition *Messages = NULL);
inline ~cdevClassDefinition ( void );
inline int addElement (cdevElementDefinition *&target,
cdevElementDefinition * element );
inline int addElement (cdevElementDefinition *& target,
char * eleName,
cdevServiceDefinition * service,
char ** serviceData,
int nItems);
inline int addDevice (char * device, char * substName = NULL );
inline int addVerb (char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems );
inline int addVerb (cdevElementDefinition * element );
inline int addAttribute (char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems );
inline int addAttribute (cdevElementDefinition * element );
inline int addMessage (char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems );
inline int addMessage (cdevElementDefinition * element );
inline int isA (char * className );
inline void asciiDump (FILE * fp = stdout );
inline void asciiDumpInstances ( FILE * fp = stdout );
inline void asciiDumpRedirector ( FILE * fp = stdout );
inline void createRedirectionTable ( void );
// *********************************************************************
// * Member access functions:
// *********************************************************************
inline char * getName ( void );
inline cdevDirectoryTable & getDirectory ( void );
inline cdevClassDefinition * getParent ( void );
inline cdevElementDefinition * getVerbs ( void );
inline cdevElementDefinition * getAttributes ( void );
inline cdevElementDefinition * getMessages ( void );
inline cdevDeviceDefinition * getDevices ( void );
inline StringHash & getRedirector ( void );
inline int getElements ( cdevDirectoryTable::ElementType type,
cdevElementDefinition ** &def,
int &nItems );
inline cdevClassDefinition * getNext ( void );
inline void setNext ( cdevClassDefinition * Next );
};
// *****************************************************************************
// * cdevClassDefinition::cdevClassDefinition :
// * This is the constructor for the class definition object. I
// *****************************************************************************
inline cdevClassDefinition::cdevClassDefinition
( cdevDirectoryTable &Master,
char *Name,
cdevClassDefinition *Parent,
cdevElementDefinition *Verbs,
cdevElementDefinition *Attributes,
cdevElementDefinition *Messages)
: directory (Master),
name (Name),
parent (Parent),
verbs (Verbs),
attributes (Attributes),
messages (Messages),
deviceHead (NULL),
deviceTail (NULL),
next (NULL)
{
}
// *****************************************************************************
// * cdevClassDefinition::~cdevClassDefinition :
// * This is the descructor for the cdevClassDefinition object. It will
// * delete the class name and each item from the elements list.
// *****************************************************************************
inline cdevClassDefinition::~cdevClassDefinition ( void )
{
cdevElementDefinition * ptr;
cdevDeviceDefinition * dPtr;
cdevRedirectorDefinition * rPtr;
StringHashIterator iter(&redirector);
delete name;
while(verbs!=NULL)
{
ptr = verbs;
verbs = verbs->getNext();
delete ptr;
}
while(messages!=NULL)
{
ptr = messages;
messages = messages->getNext();
delete ptr;
}
while(attributes!=NULL)
{
ptr = attributes;
attributes = attributes->getNext();
delete ptr;
}
while(deviceHead!=NULL)
{
dPtr = deviceHead;
deviceHead = deviceHead->getNext();
directory.getDeviceHash().remove(dPtr->getName());
delete dPtr;
}
for(iter.first(); (rPtr = (cdevRedirectorDefinition *)iter.data())!=NULL; )
{
iter++;
redirector.remove(rPtr->getName());
delete rPtr;
}
}
// *****************************************************************************
// * cdevClassDefinition::addElement :
// * This method is used to add an element (verb, attribute, or message) to
// * the cdevClassDefinition. The target parameter is a reference to the
// * list that will receive the incoming element.
// *****************************************************************************
inline int cdevClassDefinition::addElement
( cdevElementDefinition *&target,
cdevElementDefinition * element )
{
cdevElementDefinition *curr, *prev;
int result = CDEV_SUCCESS;
for(curr=target, prev=NULL;
curr!=NULL && strcmp(curr->getName(), element->getName());
curr=curr->getNext())
{
prev = curr;
}
if(curr == NULL)
{
if(prev) prev->setNext(new cdevElementDefinition(element));
else target = new cdevElementDefinition(element);
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevClassDefinition::addElement :
// * This method will create a new element and add it to the list of elements
// * that is reference by the target paremeter.
// *****************************************************************************
inline int cdevClassDefinition::addElement
(cdevElementDefinition *& target,
char * eleName,
cdevServiceDefinition * service,
char ** serviceData,
int nItems)
{
cdevElementDefinition *curr, *prev;
int result = CDEV_SUCCESS;
for(curr=target, prev=NULL;
curr!=NULL && strcmp(curr->getName(), eleName);
curr=curr->getNext())
{
prev = curr;
}
if(curr == NULL)
{
if(prev) prev->setNext(new cdevElementDefinition(eleName, service, serviceData, nItems));
else target = new cdevElementDefinition(eleName, service, serviceData, nItems);
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevClassDefinition::addDevice :
// * This method will add a new device to the device list. This device name
// * will also be placed in the hashTable in the cdevDirectoryTable object
// * specified by directory.
// *
// * Note the device name becomes the property of the cdevDeviceDefinition
// * class and should not be deleted.
// *
// * The redirection table for this device will also be created as the
// * first device is instanciated.
// *****************************************************************************
inline int cdevClassDefinition::addDevice ( char * device, char * substName )
{
int result = CDEV_SUCCESS;
if(device!=NULL && directory.getDeviceHash().find(device)==NULL)
{
cdevDeviceDefinition * def =
new cdevDeviceDefinition(directory, device, substName, *this);
if(deviceTail==NULL)
{
deviceHead = def;
deviceTail = def;
createRedirectionTable();
directory.addClassInstance(this);
}
else {
deviceTail->setNext( def );
deviceTail = def;
}
directory.addDevice(def);
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevClassDefinition::addVerb :
// * This method will add a verb to the verbs element definition list.
// *****************************************************************************
inline int cdevClassDefinition::addVerb
( char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems )
{
return addElement(verbs, eleName, service, serviceData, nItems);
}
// *****************************************************************************
// * cdevClassDefinition::addVerb :
// * This method will add a verb to the verbs element definition list.
// *****************************************************************************
inline int cdevClassDefinition::addVerb ( cdevElementDefinition * element )
{
return addElement(verbs, element);
}
// *****************************************************************************
// * cdevClassDefinition::addAttribute :
// * This method will add an attribute to the attributes element
// * definition list.
// *****************************************************************************
inline int cdevClassDefinition::addAttribute
( char * eleName, cdevServiceDefinition * service, char ** serviceData, int nItems )
{
return addElement(attributes, eleName, service, serviceData, nItems);
}
// *****************************************************************************
// * cdevClassDefinition::addAttribute :
// * This method will add an attribute to the attributes element
// * definition list.
// *****************************************************************************
inline int cdevClassDefinition::addAttribute ( cdevElementDefinition * element )
{
return addElement(attributes, element);
}
// *****************************************************************************
// * cdevClassDefinition::addMessage :
// * This method will add a message to the messages element definition list.
// *****************************************************************************
inline int cdevClassDefinition::addMessage
( char * eleName, cdevServiceDefinition * service, char ** serviceData, int nItems )
{
return addElement(messages, eleName, service, serviceData, nItems);
}
// *****************************************************************************
// * cdevClassDefinition::addMessage :
// * This method will add a message to the messages element definition list.
// *****************************************************************************
inline int cdevClassDefinition::addMessage ( cdevElementDefinition * element )
{
return addElement(messages, element);
}
// *****************************************************************************
// * cdevClassDefinition::isA :
// * This method will ascend the class hierarchy attempting to locate a
// * class with the name specified in className. It will return TRUE if this
// * class is or inherits from the specified className, or FALSE if not.
// *****************************************************************************
inline int cdevClassDefinition::isA ( char * className )
{
int result;
if(strcmp(name, className)==0) result = 1;
else if(parent!=NULL) result = parent->isA(className);
else result = 0;
return result;
}
// *****************************************************************************
// * cdevClassDefinition::asciiDump :
// * This method dumps the contents of the cdevClassDefinition to the user
// * specified file descriptor.
// *****************************************************************************
inline void cdevClassDefinition::asciiDump ( FILE * fp )
{
if(name)
{
fprintf(fp, "\nclass %s", name);
if(parent) fprintf(fp, " : %s", parent->name);
fprintf(fp, "\n\t{\n");
if(verbs!=NULL) verbs->asciiDumpList(fp, "verbs");
if(attributes!=NULL) attributes->asciiDumpList(fp, "attributes");
if(messages!=NULL) messages->asciiDumpList(fp, "messages");
fprintf(fp, "\t}\n");
}
}
// *****************************************************************************
// * cdevClassDefinition::asciiDumpInstances :
// * This method dumps the instance data of the class definition to the
// * caller specified file descriptor.
// *****************************************************************************
inline void cdevClassDefinition::asciiDumpInstances ( FILE * fp )
{
if(deviceHead!=NULL)
{
cdevDeviceDefinition * device = deviceHead;
fprintf(fp, "\n%s : \n", name);
while(device!=NULL)
{
if(device->getName()!=device->getSubstituteName())
{
fprintf(fp, "\t%s {%s}\n", device->getName(), device->getSubstituteName());
}
else fprintf(fp, "\t%s\n", device->getName());
device = device->getNext();
}
fprintf(fp, "\t;\n");
}
}
// *****************************************************************************
// * cdevClassDefinition::asciiDumpRedirector :
// * This method dumps the contents of the redirection table that is used
// * to route messages to their intended service.
// *****************************************************************************
inline void cdevClassDefinition::asciiDumpRedirector ( FILE * fp )
{
StringHashIterator iter(&redirector);
cdevRedirectorDefinition * def;
fprintf(fp, "\n/* Redirection table for class %s */\n", name);
fprintf(fp, "class %s\n\t{\n\tmessages\n\t\t{\n", name);
for(iter.first();
(def = (cdevRedirectorDefinition *)iter.data())!=NULL;
iter++)
{
def->asciiDump(fp);
}
fprintf(fp, "\t\t}\n\t}\n");
}
// *****************************************************************************
// * cdevClassDefinition::createRedirectionTable :
// * This method will read the verbs, attributes and messages and will
// * generate a redirection table that will allow the cdevDirectoryTable
// * to route requests to the correct service using the proper serviceData.
// *****************************************************************************
inline void cdevClassDefinition::createRedirectionTable ( void )
{
cdevRedirectorDefinition * def;
cdevElementDefinition ** msgPtr, ** vrbPtr, **atrPtr;
int msgCnt, vrbCnt, atrCnt;
int msgIdx, vrbIdx, atrIdx;
// *********************************************************************
// * Get a pointer to all of the verbs that are in use by the class.
// *********************************************************************
getElements(cdevDirectoryTable::MESSAGE, msgPtr, msgCnt);
getElements(cdevDirectoryTable::VERB, vrbPtr, vrbCnt);
getElements(cdevDirectoryTable::ATTRIBUTE, atrPtr, atrCnt);
// *********************************************************************
// * Process through all of the messages and add them to the
// * redirection list first. Display a warning if they are already
// * present.
// *********************************************************************
for(msgIdx=0; msgIdx<msgCnt; msgIdx++)
{
if(msgPtr[msgIdx]->getName() && msgPtr[msgIdx]->getService())
{
if(redirector.find(msgPtr[msgIdx]->getName())!=NULL)
{
cdevReportError(CDEV_SEVERITY_INFO, "CDEV Directory", NULL,
"Message %s already defined for class %s",
msgPtr[msgIdx]->getName(), name);
}
else {
def = new cdevRedirectorDefinition(strdup(msgPtr[msgIdx]->getName()), *msgPtr[msgIdx]);
redirector.insert(def->getName(), def);
}
}
}
// *********************************************************************
// * Walk through the verb list and combine them with each attribute...
// * For each verb that has a service associated with it, use the verbs
// * element definition... If the verb does not have a service, then
// * use the attributes element definition.
// *********************************************************************
for(vrbIdx=0; vrbIdx<vrbCnt; vrbIdx++)
{
if(vrbPtr[vrbIdx]->getName())
{
// *****************************************************
// * Using the verbs service.
// *****************************************************
if(vrbPtr[vrbIdx]->getService())
{
for(atrIdx=0; atrIdx<atrCnt; atrIdx++)
{
if(atrPtr[atrIdx]->getName()!=NULL)
{
char * temp = new char[strlen(vrbPtr[vrbIdx]->getName())+strlen(atrPtr[atrIdx]->getName())+2];
sprintf(temp, "%s %s", vrbPtr[vrbIdx]->getName(), atrPtr[atrIdx]->getName());
if(redirector.find(temp)!=NULL)
{
cdevReportError(CDEV_SEVERITY_INFO, "CDEV Directory", NULL,
"Message %s already defined for class %s",
temp, name);
delete temp;
}
else {
def = new cdevRedirectorDefinition(temp, *vrbPtr[vrbIdx]);
redirector.insert(def->getName(), def);
}
}
}
}
// *****************************************************
// * Using the attributes service.
// *****************************************************
else for(atrIdx=0; atrIdx<atrCnt; atrIdx++)
{
if(atrPtr[atrIdx]->getName() && atrPtr[atrIdx]->getService())
{
char * temp = new char[strlen(vrbPtr[vrbIdx]->getName())+strlen(atrPtr[atrIdx]->getName())+2];
sprintf(temp, "%s %s", vrbPtr[vrbIdx]->getName(), atrPtr[atrIdx]->getName());
if(redirector.find(temp)!=NULL)
{
cdevReportError(CDEV_SEVERITY_INFO, "CDEV Directory", NULL,
"Message %s already defined for class %s",
temp, name);
delete temp;
}
else {
def = new cdevRedirectorDefinition(temp, *atrPtr[atrIdx]);
redirector.insert(def->getName(), def);
}
}
else {
cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL,
"Neither the verb nor the message for \"%s %s\" has a service",
vrbPtr[vrbIdx]->getName(), atrPtr[atrIdx]->getName());
}
}
}
}
// *********************************************************************
// * Release the memory used to store the pointers.
// *********************************************************************
if(msgPtr) delete msgPtr;
if(vrbPtr) delete vrbPtr;
if(atrPtr) delete atrPtr;
}
// *****************************************************************************
// * cdevClassDefinition::getElements :
// * This method allows the caller to retrieve a list of all element
// * definitions of a particular type from all subclasses of the current
// * class.
// *****************************************************************************
inline int cdevClassDefinition::getElements ( cdevDirectoryTable::ElementType type,
cdevElementDefinition ** &def,
int &nItems )
{
StringHash tempHash;
cdevClassDefinition * classDef = this;
def = NULL;
nItems = 0;
do
{
cdevElementDefinition * el =
type==cdevDirectoryTable::VERB?classDef->verbs:
(type==cdevDirectoryTable::ATTRIBUTE?classDef->attributes:
classDef->messages);
for(; el!=NULL; el = el->getNext())
{
if(tempHash.find(el->getName())==NULL)
{
tempHash.insert(el->getName(), el);
nItems++;
}
}
classDef = classDef->parent;
} while(classDef!=NULL);
if(nItems!=0)
{
StringHashIterator iter(&tempHash);
def = new cdevElementDefinition * [nItems];
nItems = 0;
for(iter.first(); iter.key()!=NULL; iter++)
{
def[nItems++] = (cdevElementDefinition *)iter.data();
}
}
return nItems;
}
// *****************************************************************************
// * cdevClassDefinition::getName :
// * This method allows the caller to retrieve the name of the class.
// *****************************************************************************
inline char * cdevClassDefinition::getName ( void )
{
return name;
}
// *****************************************************************************
// * cdevClassDefinition:: :
// * This method allows the caller to retrieve the directory table that
// * owns this device.
// *****************************************************************************
inline cdevDirectoryTable & cdevClassDefinition::getDirectory ( void )
{
return directory;
}
// *****************************************************************************
// * cdevClassDefinition::getParent :
// * This method allows the caller to retrieve the class definition that
// * this class inherits from.
// *****************************************************************************
inline cdevClassDefinition * cdevClassDefinition::getParent ( void )
{
return parent;
}
// *****************************************************************************
// * cdevClassDefinition::getVerbs :
// * This method allows the caller to retrieve the lement definition list
// * containing all of the classes verbs.
// *****************************************************************************
inline cdevElementDefinition * cdevClassDefinition::getVerbs ( void )
{
return verbs;
}
// *****************************************************************************
// * cdevClassDefinition::getAttributes :
// * This method allows the caller to retrieve the element definition list
// * containing all of the classes verbs.
// *****************************************************************************
inline cdevElementDefinition * cdevClassDefinition::getAttributes ( void )
{
return attributes;
}
// *****************************************************************************
// * cdevClassDefinition::getMessages :
// * This method allows the caller to retrieve the element definition list
// * containing all of the classes messages.
// *****************************************************************************
inline cdevElementDefinition * cdevClassDefinition::getMessages ( void )
{
return messages;
}
// *****************************************************************************
// * cdevClassDefinition::getDevices :
// * This method allows the caller to retrieve the device definition list
// * containing all of the instances of the class.
// *****************************************************************************
inline cdevDeviceDefinition * cdevClassDefinition::getDevices ( void )
{
return deviceHead;
}
// *****************************************************************************
// * cdevClassDefinition::getRedirector :
// * This method allows the caller to retrieve the redirection list for
// * the class.
// *****************************************************************************
inline StringHash & cdevClassDefinition::getRedirector ( void )
{
return redirector;
}
// *****************************************************************************
// * cdevClassDefinition::getNext :
// * This method allows the caller to retrieve the next class definition in
// * the list.
// *****************************************************************************
inline cdevClassDefinition * cdevClassDefinition::getNext ( void )
{
return next;
}
// *****************************************************************************
// * cdevClassDefinition::setNext :
// * This method allows the caller to set the next class definition in the
// * list.
// *****************************************************************************
inline void cdevClassDefinition::setNext ( cdevClassDefinition * Next )
{
next = Next;
}
#endif /* _CDEV_CLASS_DEFINITION_H_ */