BIM: Design Document
Section I - Overview:
B.I.M. is an interworven mesh of two systems that are usually seperate entities in software. The client side instant messenger(CSIM) which can be used to facilitate quick conversation between individuals while archivig this data for later retrieval in a database and the message board(Group Pages) which allows for slower paced conversations between larger groups of people. The architecture of B.I.M. can be divided into four broad components, the database architecture, the networking architecture, the client side instant messenger, and the web user interface.Section II - Database Architecture:
The above diagram describes all the entities that will need to be modeled in the system. For an explanation of the ER notation, use this key. a.) Description of Entities i.) User: is a user of the system with a valid user name which allows him/her to accesss the message board as well as login to the CSIM and converse with other users. ii.) Group Page: is any discussion forum on the message board. It has a creator who specifies which users have access to that section of the message board and which do not. iii.) Contact List: is a list of users and/or groups that a user wants to have regular contact with. iv.) Alias: is a grouping of users and/or groups in a contact list that can be treated as a single entity when sending messages. v.) Message: is a message that was either sent using the CSIM or was a post on the message board. vi.) Conversation: is a grouping of messages. They are grouped by subject and participants for the CSIM and by Group Page on the message board. b.) Database Tables The above database schema had to be normalised before being stored in the database by decomposing inadequate relation schemas into schemas possessing more satisfactory properties. Normalizing the database schema prevents the storing of redundant information in seperate tables as well as prevents various update anomalies such as orphaned data in tables on deletes due to improper dependencies, inability to insert certain data due to dependency restrictions and having to update several tables on modifying a field in an entry that many entries are dependent on. While normalizing the database care was made that there was no creation of spurious tuples when JOIN operations are performed by making sure that equality conditions are always performed on attributes that are primary or foreign keys. Also all functional dependencies were preserved.Legend
Primary Key | Blue text |
Foreign Key | Underlined and Italicized Text |
Primary/Foreign Key | Blue,Italicized and Underlined Text |
Index | Bold on Yellow Background |
user_id | screen_name | wants_notification(yes, no) | first_name | last_name | job_title | pswd | home_phone | work_phone | cell_phone |
group_id | participants_id | user_id | description | name | parent_group_id |
participant_id | user_id |
participant_id | time_sent | message_id | parent_message_id | User ID | message_text |
user_id | message_id |
user_id | message_id |
user_id | alias | contact_id |
This design is a classic Client-Server Middleware architecture. On the front-end, there is a BIM Instant Messenger client that connects through a TCP/IP network to the BIM Server, which manages client connections, performs security checks, and relays information to and from the backend Relational Database.
The client server transport protocol uses always-on TCP connections, which not only provide reliable data delivery,but are also more efficient for large streams of data that may be often sent by BIM server to the client. Each packet is transformed into a binary representation by the BIM protocol parsing layer. b.) Protocol Parsing Layer The networking binary protocol layer consists of 14 portable C++ classes representing 14 different packets that a client and server are able to send to each other. It's job is to abstract away the details of the binary parser from the IM Client and Server developers, at the same time keeping the protocol portable and fast. The relationship of the protocol classes is represented by the following diagram: i.) Packet Class
Description: An abstract object that represents a generic BIM protocol Packet
Parent Class: None
Attributes:
Name |
Type |
Description |
pVersion |
32-bit unsigned integer |
Protocol version of the packet |
CommandType |
32-bit unsigned integer |
Type of packet |
Methods:
Name |
Access |
Type |
Description |
GetBinaryDataLength() |
Protected |
Pure Virtual |
Calculates the length of the binary data that would be generated from the packet (Packet header is not included) |
GenerateBinaryData() |
Protected |
Pure Virtual |
Generates binary data from the packet (Packet header is not included) |
GetStringField() |
Protected |
Static |
Gets a string field from a binary data stream |
GetIntField() |
Protected |
Static |
Gets an integer field from a binary data stream |
GetBooleanField() |
Protected |
Static |
Gets a boolean field from a binary data stream |
GetClass() |
Public |
Pure Virtual |
Returns a pointer to an instantiated instance of a specific packet class that corresponds to the requested protocol version |
GetPacketLength() |
Public |
Non-Static |
Calculates the length of the complete binary data representation of the packet, including packet header |
GeneratePacketData() |
Public |
Non-Static |
Generates complete binary data representation of the packet, including packet header |
IdentifyPacket() |
Public |
Non-Static |
Identifies the type of the packet |
GetProtocolVersion() |
Public |
Non-Static |
Returns the protocol version of the packet |
IsGroupID() |
Public |
Static |
Checks if the UID represents a valid Group ID |
IsUserID() |
Public |
Static |
Checks if the UID represents a valid User ID |
IsSystemID() |
Public |
Static |
Checks if the UID represents a valid UID of a system administrator |
ii.) ClientInit Class (Server -> Client)
Description: An object that represents an initialization packet containing client's contact list that is sent to the client right after a successful login procedure
Parent Class: Packet
Attributes:
Name |
Type |
Description |
OwnerUID |
32-bit unsigned integer |
User ID of the owner of the contact list |
vAliases |
Vector |
Vector of contact list aliases |
Methods:
Name |
Access |
Type |
Description |
SetOwner() |
Public |
Non-Static |
Sets User ID of the owner of the contact list |
AddAlias() |
Public |
Non-Static |
Adds an alias to the contact list |
RemoveAlias() |
Public |
Non-Static |
Removes an alias from the contact list |
GetOwner() |
Public |
Non-Static |
Returns the User ID of the owner of the contact list |
GetSize() |
Public |
Non-Static |
Returns the number of aliases in the contact list |
operator[]() |
Public |
Non-Static |
Returns the pointer to the copy of the alias at the specified 0-based index in the vector of aliases |
Description: An object that represents a packet containing a client request to remove an alias from the contact list
Server reply packet: ClientInit containing modified contact list
Parent Class: Packet
Attributes:
Name |
Type |
Description |
szAliasName |
String |
Name of the Alias to remove |
Methods:
Name |
Access |
Type |
Description |
SetAliasName() |
Public |
Non-Static |
Sets the name of the alias to delete |
GetAliasName() |
Public |
Non-Static |
Returns the name of the alias to delete |
iv.) Error Class (Server -> Client)
Description: An object that represents a packet containing a server response to the client describing a server error that has occurred. The server may send this packet in response to any Client->Server request.
Parent Class: Packet
Attributes:
Name |
Type |
Description |
szErrorTitle |
String |
Title of the error message |
szErrorBody |
String |
Body of the error message |
Methods:
Name |
Access |
Type |
Description |
SetTitle() |
Public |
Non-Static |
Sets the title of the error message |
SetBody() |
Public |
Non-Static |
Sets the body of the error message |
GetTitle() |
Public |
Non-Static |
Returns the title of the error message |
GetBody() |
Public |
Non-Static |
Returns the body of the error message |
v.) GroupSearch Class (Client -> Server)
Description: An object that represents a packet containing a client request to do a Group search or retrieve info for a specific group
Server reply packet: GroupSearchResponse containing information for either the specified group or all available groups
Parent Class: Packet
Attributes:
Name |
Type |
Description |
uid |
32-bit unsigned integer |
Group UID whose info is requested |
bUIDSet |
Boolean |
Boolean indicating whether a group search or a group information request needs to be performed |
Methods:
Name |
Access |
Type |
Description |
SetUID() |
Public |
Non-Static |
Sets the Group ID of the group whose information is needed |
GetUID() |
Public |
Non-Static |
Returns the GroupID of the group whose information is needed |
vi.)GroupSearchResponse Class (Server -> Client)
Description: An object that represents a packet containing a server response to a group search or info request
Parent Class: Packet
Attributes:
Name |
Type |
Description |
vGroups |
Vector |
Vector of groups |
Methods:
Name |
Access |
Type |
Description |
AddGroupInfo() |
Public |
Non-Static |
Adds GroupInfo information to the packet |
GetSize() |
Public |
Non-Static |
Returns the number of groups in the packet |
operator[]() |
Public |
Non-Static |
Returns the pointer to the copy of the group at the specified 0-based index in the vector of groups |
vii.) Login Class (Client -> Server)
Description: An object that represents a packet containing a server response to the client describing a server error that has occurred
Server reply packet: ClientInit containing user contact list
Parent Class: Packet
Attributes:
Name |
Type |
Description |
szScreenName |
String |
Unique user Screen Name that identifies a user on a BIM system |
szPassword |
String |
User’s password |
Methods:
Name |
Access |
Type |
Description |
SetScreenName() |
Public |
Non-Static |
Sets user’s Screen Name |
SetPassword() |
Public |
Non-Static |
Sets user’s password |
GetScreenName() |
Public |
Non-Static |
Returns user’s Screen Name |
GetPassword() |
Public |
Non-Static |
Returns user’s password |
viii.) Message Class (Client -> Server and Server -> Client)
Description: An object that represents a packet containing a message from a user to a list of users and/or groups
Parent Class: Packet
Attributes:
Name |
Type |
Description |
vReceivers |
Vector |
Vector of receivers of the message |
FromUID |
32-bit unsigned integer |
User ID of the sender |
szFrom |
String |
Screen Name of the sender |
szSubject |
String |
Subject of the message |
lTime |
Time |
Sending time |
szMsgText |
String |
Body of the message |
Methods:
Name |
Access |
Type |
Description |
SetSender() |
Public |
Non-Static |
Set sender's Screen Name |
AddReceiver() |
Public |
Non-Static |
Add a receiver to the message |
SetDelivered() |
Public |
Non-Static |
Set the delived flag for a specific receiver to indicate whether the message has been received or not by that receiver |
SetSubject() |
Public |
Non-Static |
Set the subject of the message |
SetTime() |
Public |
Non-Static |
Set message sending time in GMT format |
SetMsgText() |
Public |
Non-Static |
Set message body |
GetSender() |
Public |
Non-Static |
Return sender’s Screen Name |
GetReceivers() |
Public |
Non-Static |
Return the number of receivers of the message |
GetReceiver() |
Public |
Non-Static |
Return a receiver of the message |
GetDelivered() |
Public |
Non-Static |
Return the delived flag for a receiver to indicate whether the message has been received or not by that receiver |
GetSubject() |
Public |
Non-Static |
Return subject of the message |
GetTime() |
Public |
Non-Static |
Return message time in GMT format |
GetMsgText() |
Public |
Non-Static |
Get message body |
ix.) ModifyAlias Class (Client -> Server)
Description: An object that represents a packet containing a client request to modify an alias in the contact list
Server reply packet: ClientInit containing modified contact list
Parent Class: Packet
Attributes:
Name |
Type |
Description |
alias |
AliasInfo |
Alias to modify |
mode |
32-bit unsigned integer |
Mode: CREATE new alias OR MODIFY existing one |
Methods:
Name |
Access |
Type |
Description |
SetAlias() |
Public |
Non-Static |
Sets the alias to modify |
GetAlias () |
Public |
Non-Static |
Returns the alias to modify |
x.) MsgHistory Class (Server -> Client)
Description: An object that represents a packet containing client's message history
Parent Class: Packet
Attributes:
Name |
Type |
Description |
vConvers |
Vector |
Vector of conversations |
Methods:
Name |
Access |
Type |
Description |
AddConversation() |
Public |
Non-Static |
Adds a conversation to the packet |
GetSize() |
Public |
Non-Static |
Returns the number of conversations in the packet |
operator[]() |
Public |
Non-Static |
Returns the pointer to the copy of the conversation at the specified 0-based index in the vector of conversations |
xi.) RenameAlias Class (Client -> Server)
Description: An object that represents a packet containing a client request to rename an alias in the contact list
Server reply packet: ClientInit containing modified contact list
Parent Class: Packet
Attributes:
Name |
Type |
Description |
szOldName |
String |
Original Alias name |
szNewName |
String |
New Alias name |
Methods:
Name |
Access |
Type |
Description |
SetOldName() |
Public |
Non-Static |
Sets the old name of the alias |
SetNewName() |
Public |
Non-Static |
Sets the new name of the alias |
GetOldName() |
Public |
Non-Static |
Returns the old Alias name |
GetNewName() |
Public |
Non-Static |
Returns the new Alias name |
xii.) SendMsgHistory Class (Client -> Server)
Description: An object that represents a packet containing a client request to get message history
Server reply packet: MsgHistory with complete message history for the mutual history between a client and a list of users
Parent Class: Packet
Attributes:
Name |
Type |
Description |
vUsers |
Vector |
Vector of UserIDs |
Methods:
Name |
Access |
Type |
Description |
AddUser() |
Public |
Non-Static |
Sets the UserID of the person whose history is needed. One of the UserIDs has to be that of the client who is requesting his message history |
GetSize() |
Public |
Non-Static |
Returns the number of users whose message history is needed |
GetUser() |
Public |
Non-Static |
Returns the UserID at the specified 0-based index in the vector of UserIDs |
xiii.) UpdateStatus Class (Client -> Server and Server -> Client)
Description:An object that represents a packet containing a client request/notification to update user's online status to user defined or back
Parent Class: Packet
Attributes:
Name |
Type |
Description |
user |
User |
User whose status has changed |
Methods:
Name |
Access |
Type |
Description |
SetUser() |
Public |
Non-Static |
Sets the user whose status has changed |
GetUser() |
Public |
Non-Static |
Returns the user whose status has changed |
xiv.) UserSearch Class (Client -> Server)
Description: An object that represents a packet containing a client request to do a User search or retrieve info for a specific user. A search can be performed by first name and/or last name
Server reply packet: UserSearchResponse containing information for either the specified group or all available groups
Parent Class: Packet
Attributes:
Name |
Type |
Description |
mode |
32-bit unsigned integer |
Search Mode: Search or Retrieve Info |
uid |
32-bit unsigned integer |
User ID whose info is requested |
szFirstName |
String |
Case-insensitive first name of the user |
szLastName |
String |
Case-insensitive last name of the user |
Methods:
Name |
Access |
Type |
Description |
SetUID() |
Public |
Non-Static |
Sets the User ID of the user whose information is needed |
SetFirstName() |
Public |
Non-Static |
Sets the First Name of the person that is being searched for |
SetLastName() |
Public |
Non-Static |
Sets the Last Name of the person that is being searched for |
GetMode() |
Public |
Non-Static |
Returns the search mode |
GetUID() |
Public |
Non-Static |
Returns the Use ID of the user whose information is needed |
GetFirstName() |
Public |
Non-Static |
Returns the First Name of the person that is being searched for |
GetLastName() |
Public |
Non-Static |
Returns the Last Name of the person that is being searched for |
xv.)UserSearchResponse Class (Server -> Client)
Description: An object that represents a packet containing a server response to a user search or info request
Parent Class: Packet
Attributes:
Name |
Type |
Description |
vUsers |
Vector |
Vector of users |
Methods:
Name |
Access |
Type |
Description |
AddUserInfo() |
Public |
Non-Static |
Adds UserInfo information to the packet |
GetSize() |
Public |
Non-Static |
Returns the number of users in the packet |
operator[]() |
Public |
Non-Static |
Returns the pointer to the copy of the user at the specified 0-based index in the vector of groups |
c.) BIM Server
The server is a multithreaded C++ program that manages incoming client connections, performs security checks to prevent such thing as message spoofing and ensures secure client logins, and transfers information to and from connected users and the database. At startup, the server creates 2 threads to listen for new client connections and interprocess communication (IPC) messages from the Web Server. The Client Connections Listening Thread creates a new thread for each client when it connects, which at that point takes over the client connection and proceeds to communicate with it directly, terminating when the client disconnects from the server. The Web Notifications Listening Thread uses IPC techniques, such as Events and FileMapping objects, to listen for notifications from the ASP Web Server and retrieves and dispatches unsent messages from the database to users included in the notification.
The server keeps a global hash table of online users that keeps the socket information about each connected user that is used by all the Client Threads, as well as the Web Notifications Listening Thread, to send messages and other packets directly to each user.
Section III - ClientSide Instant Messenger:
After the user logs in, the client sends the username and password to the server. The server then sends the contact list, which the client receives and displays. The contact list is the main point of interaction for the user, from which message may be sent and received, information can be obtained for users and groups, or history can be requested. The contact list is organized by aliases, with all users in an alias as sub-items under the alias. Some users are not in any alias in which case the user is displayed at the top level of the contact list. The contact list also displays the status of each user on it. Group Pages are always considered to be online.
When an incoming message is received, the sender's icon on the contact list, as well as the tray icon for the client flash between the status indicator and the message icon. If the sender of the message is not on the user's contact list, the message is immediately displayed. The client is capable of storing as many messages as system memory permits before they are viewed by the user.
When the user clicks on a user for which there is a pending incoming message, the message is displayed. The incoming message window allows the user to reply to the sender only, via the "Reply" button, or to reply to the sender and all other recipients via the "Reply All" button. The user may also simply close the message by choosing the "Ok" button.
The user may send a message to one or more people either directly, or in reply to another message. If replying to another message the subject is automatically transferred to the reply message. The user may send a message to a user or group by double clicking them on the contact list when there are no incoming messages from them. If the user double clicks on an alias, an outgoing message is created with all members of that alias as recipients. The user may add more recipients to a message by clicking on a user, group, or alias on the contact list and dragging it into the message's recipient list. If an alias is added, all members of the alias who are not already in the recipient list are added. The user may remove recipients from the list via the delete button located below the recipient list.
Searching for users or groups is done via the search button located below the contact list. Clicking on this button brings up a window which allows the user to either specify the name of the person who he wishes to search for, or to search or groups. When the user chooses one of these, the request is sent to the server, which processes the request and sends the information back. When the client receives the reply, the search window is closed and the results are displayed. Any of the search results may be dragged to the contact list. If a search result is dropped in an alias on the contact list, then that user or group is added to that alias. If the result is dropped elsewhere on the contact list, the user or group is added to the top level of the contact list, outside of all aliases.
Aliases can also be renamed and deleted. The user may rename an alias by selecting "Rename" from the popup menu and then editing the name of the alias. Similarly, the "Delete" option on the contact list will remove an alias and everyone in it from the contact list. The popup menu also allows the user to obtain information about a user or group, or to get conversation history with a specific user or group. The history window shows all messages sent to or received from a specific user. The history that is displayed may be searched to find the appearance of words that the user is looking for in the various messages.
The CSIM client allows the user to have three online states: online, user defined, and offline. When the user is in a user defined status, the user may specify the status name and message. The status of each user is displayed next to their names in the contact list. The user may change his own status via the menu at the top of the client window, the button below the contact list, or the tray icon's popup menu. When going from offline to online, the client sends a login request to the server. If the client loses its connection to the server while the user is online, it automatically goes into offline mode to notify the user that no connection to the server is available.
The IM Client has two threads- one that listens for incoming messages and the main thread, which
handles the GUI elements. The second thread is needed to ensure that incoming packets are received
quickly without interfereing with the use of the GUI due to blocking calls.
When the listening thread needs to interact with an element of the GUI it uses the Synchronize method.
The Synchronize method takes a function pointer as an argument and executes that function on the main
GUI thread to prevent deadlocks.
The GUI was developed using Borland's C++ Builder. C++ Builder comes with Borland's Visual Component
Library (VCL), a set of classes which lets one develop Window's GUIs in an object oriented manner.
The second thread (the 'listener thread') is an instance of a class which extends TThread. TThread a
class from the VCL which encapsulates a Windows Thread. The listener thread has the socket connection.
All access to the socket connection with the server is done through instance methods in that class.
The Execute method of the listener thread is what is run asynchronously when the Thread is run (similar
to the run() method in a java Thread Object). The listener thread's execute method reads from the
socket and deals with the incoming packets appropriately. All data going out on the socket goes
through the WriteToSocket method in the listener thread instance. Since all data to the socket goes
through only two places, changing the way the data is transmitted would be easy- for example, if we
were to want to add encryption, it could be quickly added by inserting the encryption call in the
WriteToSocket method before the data is sent out and the decryption call in the Execute method where
the data is read.
Section IV - Web User Interface:
To achieve it's user interface goals, BIM needed a look and feel that is in many ways unprecedented in the web today. The design of today's standard web technologies prevent sophisticated user interfaces from being built because nearly any change to the page requires both a server fetch and page refresh. Also, to get updates on rapidly changing information, the user must manually refresh the page. BIM solves many of these problems by using many next generation browser features and W3C standards.
|
||||||||||||
BIM's design is an evolution of the classic three tier design. Three tier design is the enterprise equivalent of model-view-controller. In a traditional three tier application, the "model" or state of the system is held in a SQL database. There exist data objects which represent state. These data objects map directly to one or more tables. For performance and flexibility, the database may be highly normalized. For instance, a person's name, address and phone number may be held in different tables. A data object is an abstraction on the database. Upon initialization, a well designed data object would do the appropriate database queries so that it represents the proper conceptual state. Using data objects allows for both a high performance highly flexible database as well as a clean framework for the business logic. The data objects also handle the locking of system resources and data integrity. Even if the internals of the database need changing, the only code that needs to be modified. This way the system and the database is decoupled in such a way as to permit independent development. Once the set of data objects, or data layer is in place, a set of business objects which transactionally handle system operations. For instance, a Transfer object may use Person and Account objects to transfer money from one account to another. In MVC terms, the business layer is the "controller."
The final tier of the architecture is the presentation layer. The presentation layer acts as the "view" in that it shows the user the appropriate aspects of the model and gives them access to the controller. In most enterprise implementations, the presentation layer consists of a server side code which generates HTML and a browser capable of rendering it.
The unique requirements of BIM forced a transition to a less rigid and more powerful architecture. In traditional three tier design, almost all of the functionality except for HTML rendering is done on the server. This is appropriate because it keeps the application logic in a safe, protected and controlled space. The browser has traditionally been an unpredictable, unreliable and limited platform.
Since BIM would not be possible on a traditional design, compromises had to be made in terms of browser requirements. Today, BIM will only work with Microsoft Internet Explorer 5.5 with the second version of Microsoft's XML parser. This compromise, of course, restricts potential use of BIM today, but we are confident that IE 5.5 and Netscape 6.0 will one day be standard. The most significant reasons for justifying such extreme requirements are the DOM and XML technologies.
The Document Object Model, as defined by W3C Document Object Model(DOM) Level 2 Core Specification, provides a rich object model supporting dynamic manipulation of a document in real time. Through the DOM, a scripting host can traverse and modify an exposed and HTML node tree.
BIM uses such capabilities to modify only the parts of the page that are appropriate rather than having the server regenerate it in its entirety. For instance, the BIM presentation layer could modify this table and change "Shady Grove" to "The New Shady Grove" seemlessly without a page refresh. Along with such capabilites come many challenges. Firstly, nearly the entire presentation layer needs to reside on the client. Although such a method to distribute work scales very well,slower computers may provide inadaquate performance for usable operation. Therefore the presentation logic must be designed for performance. The IE 5.5 implementation is generally quite fast, however, operations that require the more than a small part of the page to violate its bounding box may potentially make the page unusably slow. In addition to raw performance, one of the main reasons for this design is to maintain a consistent context for the user. During a page refresh, the user's context is generally violated and the user must momentarily reorient to continue working. Although the disorientation is subtle and and acceptable for most tasks, real time colaboration should be as seemless as possible. To maintain perfect consistency, content updates must avoid changing other aspects of the page.
Since BIM's presentation layer is completely on the browser and in a different process space (and potentially continent) from the server, a means of communication is necessary. Luckily, XML over HTTPS provides a clean, elegant and secure solution.
Extensible Markup Language, abbreviated XML, describes a class of data objects called XML documents and partially describes the behavior of computer programs which process them. XML is an application profile or restricted form of SGML, the Standard Generalized Markup Language [ISO 8879]. By construction, XML documents are conforming SGML documents.
XML documents are made up of storage units called entities, which contain either parsed or unparsed data.
Parsed data is made up of characters, some of which form
Essentially,data is transferred to the browser whenever content needs an update. The data is then transformed using Extensible Stylesheet Language (XSL/XSLT). XSLT is a XML based declarative language used to convert from one xml schema to another. This works well for presentation since HTML is a valid XML language. In addition to making it easy to convert data into usable HTML, XSLT makes BIM faster and more flexible. Since the XSLT is done on the client, fewer server resources need to be dedicated to presentation. XSLT style sheets may be replaced to alter the look and feel of the page without changing either the XML or the browser code.
The first step in content update is the xml generation. BIM uses Microsoft Active Server Pages running on Microsoft Internet Information Server to generate XML from a SQL database. The XML is then transferred to the browser via HTTPS. Next, BIM code running in the browser transforms the XML data into HTML. BIM then feeds that HTML to the proper node in the DOM. The result is a seamless natural content update without any disorienting page refresh.
The BIM user interface consists of three major components
The contact list shows the user the online status of their contacts. The user may also select one of the groups from the groups pane and traverse the conversation in the conversation pane.
A critical aspect of creating BIM is to ensure database integrity. Fortunately, XML provides a technology called Document Type Definitions. DTDs are formal definitions of what a certain type of XML document may look like. If the database has lost integrity, and improper XML is being generated, the XML validater will detect the error by checking it against the DTD.