Here is an example showing how classes can be contained within other classes, using an arbitrary collection.
This example expands on the simple one to add another class EmployeePosition; objects of this type will be contained in a simple linked list within an Employee object. Note that the persistence mechanism doesn't care how the collection is implemented; all it requires is an interface to the collection.
In the following example, persistence code has again been shown in blue highlight;list management code has been shown in grey highlight.
#include <stdio.h>
#include "xmlpersist.h"
class EmployeePosition : public XMLPersistent
{
public:
int m_iDepartment;
char* m_pszTitle;
char* m_pszFromDate;
char* m_pszToDate;
EmployeePosition* m_pNext;
EmployeePosition()
{
m_iDepartment = 0;
m_pszTitle = NULL;
m_pszFromDate = NULL;
m_pszToDate = NULL;
m_pNext = NULL;
}
~EmployeePosition()
{
DeleteDynamicString(m_pszTitle);
DeleteDynamicString(m_pszFromDate);
DeleteDynamicString(m_pszToDate);
if (m_pNext != NULL)
delete m_pNext;
}
DECLARE_XMLPERSIST_CLASS;
};
// Since this example includes a new class EmployeePosition, we have to add another
// data exchange macro block to handle it:
BEGIN_XMLPERSIST_CLASS(EmployeePosition,position)
XMLPERSIST_ITEM(m_iDepartment,department)
XMLPERSIST_ITEM(m_pszFromDate,from-date)
XMLPERSIST_ITEM(m_pszToDate,to-date)
BEGIN_XMLPERSIST_CONTENTS
XMLPERSIST_CONTENTS(m_pszTitle)
END_XMLPERSIST
class Employee : public XMLPersistent
{
public:
char* m_pszName;
int m_iEmployeeNumber;
int m_iDepartment;
char* m_pszResume;
EmployeePosition* m_pPositionList;
EmployeePosition* m_pLastPosition;
Employee()
{
m_pszName = NULL;
m_iEmployeeNumber = 0;
m_iDepartment = 0;
m_pszResume = NULL;
m_pPositionList = NULL;
m_pLastPosition = NULL;
}
~Employee()
{
DeleteDynamicString(m_pszName);
DeleteDynamicString(m_pszResume);
if (m_pPositionList != NULL)
delete m_pPositionList;
}
AddPositionToList(EmployeePosition* pPosition)
{
if (m_pPositionList == NULL)
{
m_pPositionList = pPosition;
}
else
{
m_pLastPosition->pNext = pPosition;
}
m_pLastPosition = pPosition;
}
XML_BOOL PositionListEnumerator(XMLStorage *pXMLStorage, const char *pszTag)
{
for (EmployeePosition* pItem = m_pPositionList; pItem != NULL; pItem = pItem->m_pNext)
{
if (!pItem->XMLTransfer(pXMLStorage, pszTag))
return FALSE;
}
}
void PositionListInitializer()
{
if (m_pPositionList != NULL)
delete m_pPositionList;
m_pPositionList = NULL;
m_pLastPosition = NULL;
}
XML_BOOL PositionListFactory(XMLStorage *pXMLStorage, const char *pszTag)
{
AddPositionToList(new EmployeePosition);
return (m_pLastPosition->XMLTransfer(pXMLStorage, pszTag));
}
DECLARE_XMLPERSIST_CLASS;
};
// This data exchange macro block is identical to that of the previous example, except for
// the addition of one new macro to handle the list.
BEGIN_XMLPERSIST_CLASS(Employee,employee)
XMLPERSIST_ITEM(m_pszName,name)
XMLPERSIST_ITEM(m_iEmployeeNumber,employee-number)
XMLPERSIST_ITEM(m_iDepartment,department)
BEGIN_XMLPERSIST_CONTENTS
XMLPERSIST_CONTENTS(m_pszResume)
XMLPERSIST_COLLECTION(PositionListEnumerator, PositionListInitializer,
PositionListFactory, position)
END_XMLPERSIST
main(int argc, char* argv[])
{
Employee anEmployee;
XMLStorage xmlObject;
if (!xmlObject.ReadFile(&anEmployee, argv[1]))
{
printf ("read file failed: error code = %d; message = %s\n",
xmlObject.m_Exception.m_Code,
xmlObject.m_Exception.Message());
}
printf ("Employee Name: %s\nEmployee Number: %d\nDepartment: %d\nResume:\n%s\n",
anEmployee.m_pszName, anEmployee.m_iEmployeeNumber, anEmployee.m_iDepartment,
anEmployee.m_pszResume);
for (EmployeePosition* pItem = m_pPositionList; pItem != NULL; pItem = pItem->m_pNext)
{
printf ("Department: %d Title: %s From: %s To: %s\n",
pItem->m_iDepartment, pItem->m_pszTitle, pItem->m_pszFromDate, pItem->m_pszToDate);
}
XMLPersistent::SetDynamicString(anEmployee.m_pszName, "John Smith");
anEmployee.m_iEmployeeNumber = 101;
anEmployee.m_iDepartment = 10;
XMLPersistent::SetDynamicString(anEmployee.m_pszResume,
"Resume of John Smith\n",
"Contact Information...\n"
"Career Summary...\n"
"Work History...\n"
"Education...\n"
"Interests...\n"
);
AddPositionToList(new EmployeePosition);
anEmployee.m_pLastPosition->m_iDepartment = 5;
XMLPersistent::SetDynamicString(anEmployee.m_pLastPosition->m_pszTitle, "Senior Developer");
XMLPersistent::SetDynamicString(anEmployee.m_pLastPosition->m_pszFromDate, "20-Jan-2001");
XMLPersistent::SetDynamicString(anEmployee.m_pLastPosition->m_pszToDate, "01-Apr-2002");
AddPositionToList(new EmployeePosition);
anEmployee.m_pLastPosition->m_iDepartment = 10;
XMLPersistent::SetDynamicString(anEmployee.m_pLastPosition->m_pszTitle, "Manager, IT");
XMLPersistent::SetDynamicString(anEmployee.m_pLastPosition->m_pszFromDate, "01-Apr-2002");
if (!xmlObject.WriteFile(&anEmployee, argv[1]))
{
printf ("write file failed: error code = %d; message = %s\n",
xmlObject.m_Exception.m_Code,
xmlObject.m_Exception.Message());
}
} |
If you were to build and run this example, specifying the same file as in the previous example, you would get the following:
| Written to a file as named on the command line: | Written to standard output: |
<employee name="John Smith"
employee-number="101"
department="10">
<position
department="5"
from-date="20-Jan-2001"
to-date="01-Apr-2002">Senior Developer</position>
<position
department="10"
from-date="01-Apr-2002"
to-date="">Manager, IT</position>
Resume of John Smith
Contact Information...
Career Summary...
Work History...
Education...
Interests...
</employee> |
Employee Name: John Smith Employee Number: 101 Department: 10 Resume: Resume of John Smith Contact Information... Career Summary... Work History... Education... Interests... |
| Note: as with the previous example, the
actual XML file may not appear exactly as shown; newlines have been added for clarity. |
The action of the program has been to add items to the list, which was successfully traversed to produce the XML output.
If the application is run again, giving it its own output, we will get the following result:
| Written to a file as named on the command line: | Written to standard output: |
<employee name="John Smith"
employee-number="101"
department="10">
<position
department="5"
from-date="20-Jan-2001"
to-date="01-Apr-2002">Senior Developer</position>
<position
department="10"
from-date="01-Apr-2002"
to-date="">Manager, IT</position>
<position
department="5"
from-date="20-Jan-2001"
to-date="01-Apr-2002">Senior Developer</position>
<position
department="10"
from-date="01-Apr-2002"
to-date="">Manager, IT</position>
Resume of John Smith
Contact Information...
Career Summary...
Work History...
Education...
Interests...
</employee> |
Employee Name: John Smith
Employee Number: 101
Department: 10
Resume:
Resume of John Smith
Contact Information...
Career Summary...
Work History...
Education...
Interests...
Department: 5 Title: Senior Developer From: 20-Jan-2001 To: 01-Apr-2002
Department: 10 Title: Manager, IT From: 01-Apr-2002 To: |
This demonstrates that the list contained in the XML file was successfully traversed, and the list created by the original run was properly re-created in memory. Since the application simply adds the same items over again, we get the result shown, with the list duplicated in the XML file.
Copyright © 2002 by rObjects. All rights reserved.