#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; msgIdxgetName() && 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; vrbIdxgetName()) { // ***************************************************** // * Using the verbs service. // ***************************************************** if(vrbPtr[vrbIdx]->getService()) { for(atrIdx=0; atrIdxgetName()!=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; atrIdxgetName() && 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_ */