//============================================================================= // File: msgcmp.h // Contents: Declarations for DwMessageComponent // Maintainer: Doug Sauder // WWW: http://www.fwb.gulf.net/~dwsauder/mimepp.html // // Copyright (c) 1996, 1997 Douglas W. Sauder // All rights reserved. // // IN NO EVENT SHALL DOUGLAS W. SAUDER BE LIABLE TO ANY PARTY FOR DIRECT, // INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF // THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF DOUGLAS W. SAUDER // HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // DOUGLAS W. SAUDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT // NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A // PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" // BASIS, AND DOUGLAS W. SAUDER HAS NO OBLIGATION TO PROVIDE MAINTENANCE, // SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. // //============================================================================= #ifndef DW_MSGCMP_H #define DW_MSGCMP_H #ifndef DW_CONFIG_H #include #endif #ifndef DW_STRING_H #include #endif #if !(defined(__DECCXX) && defined(__linux__)) #include #endif //============================================================================= //+ Name DwMessageComponent -- Abstract base class for all message components //+ Description //. {\tt DwMessageComponent} is the root of an inheritance hierarchy from //. which all MIME message components are derived. Thus, //. {\tt DwMessageComponent} defines important features that are inherited by //. nearly all other classes that represent components of a MIME message. //. These features are the following: //. //. \begin{enumerate} //. \item //. A string representation. The {\tt DwMessageComponent} class provides //. a member function {\tt FromString(const DwString&)} to set the string //. representation and a member function {\tt AsString()} to get the //. string representation. //. //. \item //. A broken-down, or parsed, representation. An RFC-822 date-time, //. for example, has a year, month, day, hour, minute, second, and //. time zone as elements of its broken-down representation. //. {\tt DwMessageComponent} does not deal directly with the //. broken-down representation, since it is component-specific. //. Derived classes bear all the responsibility for their broken-down //. representations. //. //. \item //. A parse method to extract the broken-down representation from //. the string representation. In the {\tt DwDateTime} class, for //. example, the parse method extracts the year, month, day, hour, //. minute, second, and time zone from the RFC-822 {\it date-time} //. contained in the string representation. {\tt DwMessageComponent} //. provides a pure virtual function {\tt Parse()}, which executes //. the parse method for a derived class. //. //. \item //. An assemble method to convert the broken-down representation to //. a string representation. This is the opposite of the parse method. //. In the {\tt DwDateTime} class, for example, the assemble method //. creates an RFC-822 {\it date-time} string from values of the //. year, month, day, hour, minute, second, and time zone. //. {\tt DwMessageComponent} provides a pure virtual function //. {\tt Assemble()}, which executes the assemble method for //. a derived class. //. //. \item //. An is-modified flag. When the string representation and the //. broken-down representation are consistent, the assemble //. method does not need to be executed. The is-modified flag is //. cleared when the two representations are consistent, and is set //. when they are inconsistent. The flag is set automatically //. whenever a {\tt DwMessageComponent} object's broken-down //. representation is changed by calling one of the object's member //. functions, and it is cleared when the assemble or parse method //. is executed. {\tt DwMessageComponent} also provides a member //. function {\tt SetModified()} which forces the is-modified flag //. to be set. //. //. \item //. A parent. Most message components are part of another component. //. A collection of headers is part of a message or body part, a header //. field is part of a collection of headers, a field-body is part //. of a header field, and so on. The parent of //. a component is the component that contains it. This tree structure //. is important, since a component's parent must be parsed before the //. component can be. Also, a component's string representation must //. be assembled before its parent's. To maintain consistency in the //. tree, whenever a component's is-modified flag is set, //. the component notifies its parent to also set its is-modified flag. //. In this way, an is-modified flag set anywhere in the tree always //. propagates up to the root component. //. //. \item //. Children. The preceding discussion about a component's parent is //. relevant to an understanding of a component's children. A component's //. parse method calls the parse methods of its children //. after it has executed its own parse method (and, in some cases, created //. all of its children). //. Also, a component typically calls the assemble method of its //. children before it executes its own. A component's child may request //. that the component set its is-modified flag. //. {\tt DwMessageComponent} does not deal directly with children. //. Derived classes bear all the responsibility for handling their //. children. //. \end{enumerate} //============================================================================= //+ Noentry ~DwMessageComponent _PrintDebugInfo mString mIsModified mParent //+ Noentry mClassId mClassName class DW_EXPORT DwMessageComponent { private: DwUint32 mMagicNumber; public: enum componentType { kCidError=-1, kCidUnknown=0, kCidAddress, kCidAddressList, kCidBody, kCidBodyPart, kCidDispositionType, kCidMechanism, kCidMediaType, kCidParameter, kCidDateTime, kCidEntity, kCidField, kCidFieldBody, kCidGroup, kCidHeaders, kCidMailbox, kCidMailboxList, kCidMessage, kCidMessageComponent, kCidMsgId, kCidText }; //. Class identifier enumeration DwMessageComponent(); DwMessageComponent(const DwMessageComponent& aCmp); DwMessageComponent(const DwString& aStr, DwMessageComponent* aParent=0); //. The first constructor is the default constructor, which sets the //. {\tt DwMessageComponent} object's string representation to the //. empty string and sets its parent to NULL. //. //. The second constructor is the copy constructor, which performs //. a deep copy of {\tt aCmp}. The parent of the new //. {\tt DwMessageComponent} object is set to NULL. //. //. The third constructor copies {\tt aStr} to the new //. {\tt DwMessageComponent} object's string representation and sets //. {\tt aParent} as its parent. In typical cases, the virtual //. member function {\tt Parse()} should be called immediately after //. this constructor to parse the new {\tt DwMessageComponent} object //. and all of its children into their broken-down representations. virtual ~DwMessageComponent(); const DwMessageComponent& operator = (const DwMessageComponent& aCmp); //. This is the assignment operator, which performs a deep copy of //. {\tt aCmp}. virtual void Parse() = 0; //. A pure virtual function which provides an interface to the parse //. method. The parse method, implemented in derived classes, is //. responsible for extracting the broken-down representation from //. the string representation. In some derived classes, such as //. {\tt DwHeaders}, the parse method is also responsible for creating the //. children of the object. (In the case of {\tt DwHeaders}, the children //. created are the {\tt DwField} objects that represent the {\it field}s //. contained in the {\it headers}.) The {\tt Parse()} function always //. calls the {\tt Parse()} function of all of its children. virtual void Assemble() = 0; //. A pure virtual function which provides an interface to the //. assemble method. The assemble method, implemented in derived //. classes, is responsible for creating the string representation //. from the broken-down representation. In other words, the //. assemble method is the opposite of the parse method. Before //. assembling its string representation, the assemble method calls //. the assemble method of each of its children. In this way, the //. entire tree structure that represents a message may be traversed. //. If the is-modifed flag for a {\tt DwMessageComponent} is cleared, //. the {\tt Assemble()} function will return immediately without //. calling the {\tt Assemble()} function of any of its children. virtual DwMessageComponent* Clone() const = 0; //. Creates a new {\tt DwMessageComponent} on the free store that is of //. the same type as, and has the same value as, this object. The //. basic idea is that of a ``virtual copy constructor.'' void FromString(const DwString& aStr); void FromString(const char* aCstr); //. Sets the object's string representation. {\tt aCstr} must be //. NUL-terminated. This member function does not invoke the parse //. method. Typically, the virtual member function {\tt Parse()} //. should be called immediately after this member function to parse //. the {\tt DwMessageComponent} object and all of its children into //. their broken-down representations. See also //. {\tt DwMessageComponent::Parse()} const DwString& AsString(); //. Returns the {\tt DwMessageComponent} object's string representation. //. The assemble method is not called automatically. Typically, the //. {\tt Assemble()} member function should be called immediately before //. this member function to insure that the broken-down representation //. and the string representation are consistent. See also //. {\tt DwMessageComponent::Assemble()}. DwMessageComponent* Parent(); //. Returns the {\tt DwMessageComponent} object that is the parent //. of this object. void SetParent(DwMessageComponent* aParent); //. Sets {\tt aParent} as the {\tt DwMessageComponent} object's parent. DwBool IsModified() const; //. Returns 1 if the is-modified flag is set for this //. {\tt DwMessageComponent} object. void SetModified(); //. Sets the is-modified (dirty) flag for this {\tt DwMessageComponent} //. object and notifies the object's parent to also set its is-modified //. flag. int ClassId() const; //. Returns an integer id for the object's class. const char* ClassName() const; //. Returns the name of the class as a NUL-terminated //. char string. int ObjectId() const; //. Returns a object id that is unique among all DwMessageComponent //. objects. const char* partId() const { return mId.c_str(); } void SetPartId( DwString id ) { mId = id; } // set or get a unique string for that part protected: DwString mString; // String representation DwBool mIsModified; // Is-modified flag DwMessageComponent* mParent; // Component that contains this component componentType mClassId; // Class identifier for runtime type identification const char* mClassName; // Class name for runtime type identification DwString mId; // unique indentifier private: static const char* const sClassName; public: virtual void PrintDebugInfo(std::ostream& aStrm, int aDepth=0) const; //. This virtual function //. prints debugging information about this object to {\tt aStrm}. //. It will also call {\tt PrintDebugInfo()} for any of its child //. components down to a level of {\tt aDepth}. //. //. This member function is available only in the debug version of //. the library. virtual void CheckInvariants() const; //. Aborts if one of the invariants of the object fails. Use this //. member function to track down bugs. //. //. This member function is available only in the debug version of //. the library. protected: void _PrintDebugInfo(std::ostream& aStrm) const; }; #endif