BREW Scheduler Supporting vCalendar - 3 / 7 -
Data Structure
The VCalendarFile class is basically the VCalendar class with added file I/O capabilities. VCalendarFile class inherits from VCalendar and has member variables for file name and status flag, in addition to member functions for file I/O.
class VCalendarFile : public VCalendar {
private:
SFXPath _fileName; // for file name
SFXAnsiString _flag;
// "n " : create new, "m " : modify, "d " : delete
public:
Void SetFileName(SFXPathConstRef fileName);// Sets file name
Void SetFlag(SFXAnsiStringConstRef flag);// Sets the flag
SFXPath GetFileName(Void) const; // Returns the file name
SFXAnsiString GetFlag(Void) const;// Returns flag status
SFCError SaveToFile(Void) const; // Write onto file
SFCError LoadFromFile(Void); // Read from file
//
...
};
A file is necessary to contain the data of VCalendar.
In addition, the VCalCollection class manages the instance variables of the VCalendarFile class. This class is declared as a memmber variable of its application class.
class VCalCollection {
private:
// Manage VCalendarFile variab
// This list should be always ordered by date ( _startDT )
SFXList<VCalendarFilePtr> _list;
SFXAnsiString _lastSyncTime; // The last synchronized time with server
public:
SFCError ReadIndexFile(Void); // Read from file
SFCError WriteIndexFile(Void); // Write to file
//
...
}
SFXList is used for saving instance variables of VCalendarFile.
When an element is inserted into this list, it should be ordered by the value of _startDate.
If the elements are sorted, it is useful to display a series of dates on the calendar, and mark the number of data items that were entered on that day.
Inserting an Element
// add an element onto VCalCollection
Void VCalCollection::Append(VCalendarFilePtr vcalendar)
{
SFXDateConst date1(vcalendar->GetStartDate());
Bool isInsert = false;
SIntN i;
// The flag that indicates a new creation is set.
vcalendar->SetFlag("n");
// Search for the position where the element is to be inserted
// Data must be sorted.
for (i = 0; i < _list.GetSize(); ++i) {
// Get the startDate of i th element
SFXDate date2 = _list.Get(i)->GetStartDate();
if (date1 <= date2) { // Compare the StartDates
_list.Insert(i, vcalendar); // Insert an element
isInsert = true;
break;
}
}
// If the insertion position is not found
if (!isInsert) {
_list.Append(vcalendar); // Append it to the end
}
vcalendar->SaveToFile(); // Save data to file
WriteIndexFile(); // Update index
return;
}
The above procedure is as follows.
- Search for the positon where an element is to be inserted by comparing it with each other element included in the _list. The criteria being compared here is ( startDate ).
- Insert an element into _list with Insert() when the position is found
- Append an element at the end of _list with Append() if the position is not found
- Save the data with an inserted element as a file by using the SaveToFile() function of VCalendar
- Update an index file by using WriteIndexFile()
Dates are compared by using comparison operators like "date1 <= date2".
Implement SaveToFile () of VCalendarFile
// save data as file
SFCError VCalendarFile::SaveToFile(Void) const
{
SFCError error;
SFXFile file;
SFXAnsiStringStreamWriter writer;
SFXPath fileName(DIR_NAME + _fileName.Get());
SFXPath temp;
SFXAnsiString content;
// Get temporary file name
error = SFXFile::GetTemporaryPath(SFXPath(DIR_NAME), &temp);
if (error == SFERR_NO_ERROR) {
// Make temporary file
error = file.OpenReadWrite(temp);
if (error == SFERR_NO_ERROR) {
// Convert from VCalendar class into string in vCalendar format
Export(&content);
// Get stream for writing
error = file.GetStreamWriter(content.GetLength(), &writer);
if (error == SFERR_NO_ERROR) {
// Write to file
writer << content;
writer.Flush();
}
// Close file
file.Close();
}
}
if (error == SFERR_NO_ERROR) {
// Delete old file
SFXFile::Remove(fileName);
// Rename temporary file to original name
error = SFXFile::Rename(temp, fileName);
}
return error;
}
WriteIndexFile() is the function that saves the file names of VCalendar data as index files with the following format.
20080324T031654Z // Last updated time filename1 - // Filename, tab(\t), flag filename2 d filename3 f ...
Implement WriteIndexFile() of VCalCollection
// write onto file
SFCError VCalCollection::WriteIndexFile(Void)
{
SFCError error;
SFXFile file;
SFXAnsiStringStreamWriter writer;
SFXPath fileName(DIR_NAME INDEX_FILE_NAME);
SFXPath temp;
SFXAnsiString content;
// Get temporary file name
error = SFXFile::GetTemporaryPath(SFXPath(DIR_NAME), &temp);
if (error == SFERR_NO_ERROR) {
// Make temporary file
error = file.OpenReadWrite(temp);
if (error == SFERR_NO_ERROR) {
// Get stream for writing
error = file.GetStreamWriter(1024, &writer);
if (error == SFERR_NO_ERROR) {
// Write to file
writer << _lastSyncTime << "\r\n";
writer.Flush();
SFXList<VCalendarFilePtr>::Enumerator etor
= _list.GetEnumerator();
while(etor.HasNext()) {
VCalendarFilePtr vcal = etor.GetNext();
writer << vcal->GetFileName().Get() << " "
<< vcal->GetFlag() << "\r\n";
writer.Flush();
}
}
// Close file
file.Close();
}
}
if (error == SFERR_NO_ERROR) {
// Delete old file
SFXFile::Remove(fileName);
// Rename temporary file to original name
error = SFXFile::Rename(temp, fileName);
}
return error;
}
Enumrator is used for processing each element of SFXList. The HasNext() function is used to check whether the next element exists and GetNext() returns that element.
Instance of VCalCollection
There is the only one instance of VCalCollection in this apllication, and it will be referred to by a variety of other classess.
In general, variables available at any part of an application like this are placed in an application class, which is automatically generated by SophiaFramework Application Wizard when creating new project.
SyncScheduler Application Class
class SyncScheduler : public SFRApplication {
private:
VCalCollection _vcalCollection;
//
...
public:
static VCalCollectionPtr GetVCalCollection(Void);
//
...
};
// get instance of VCalCollection
VCalCollectionPtr SyncScheduler::GetVCalCollection(Void)
{
return &static_cast<SyncSchedulerPtr>(GetInstance())
->_vcalCollection;
}
Thanks to the preceding code, the instance of VCalCollection is available at any point in the program, and is accessed as follows:
VCalCollectionPtr collection = SyncScheduler::GetVCalCollection();
Load Data
Data is loaded from file when the application starts.
// Constructor
SyncScheduler::SyncScheduler(Void) static_throws
{
....
_vcalCollection.ReadIndexFile();
...
}
ReadIndexFile() to read data from index file
// load all the data from file
// 1st, read index file
// 2nd, analyze index file
// 3rd, read data into VCalCollection from each file
SFCError VCalCollection::ReadIndexFile(Void)
{
SFCError error;
SFXFile file;
SFXAnsiStringStreamReader reader;
UInt32 size;
SFXAnsiString string;
// Get file size
error = SFXFile::GetSize(SFXPath(DIR_NAME INDEX_FILE_NAME), &size);
if (error == SFERR_NO_ERROR) {
// Open file
error = file.OpenReadOnly(SFXPath(DIR_NAME INDEX_FILE_NAME));
if (error == SFERR_NO_ERROR) {
// Get stream for reading
error = file.GetStreamReader(size, &reader);
if (error == SFERR_NO_ERROR) {
reader.Fetch();
// Read from file
reader >> string;
}
file.Close();
}
}
if (error == SFERR_NO_ERROR) {
SInt32 c1 = 0;
SInt32 c2 = 0;
// Search for end of line
c2 = string.IndexOf('\n');
// Trim blank characters
_lastSyncTime = string.Substring(0, c2).Trim();
++c2;
while ((c1 = string.IndexOf(' ', c2)) > -1) {
SFXPath filename(string.Substring(c2, c1));
c2 = string.IndexOf("\r\n", c1);
SFXAnsiString flag(string.Substring(c1 + 1, c2));
c2 += 2; // size of "\r\n"
VCalendarFilePtr vcal = ::new VCalendarFile(filename, flag);
vcal->LoadFromFile(); // Read vCalendar data from file
_list.Append(vcal);
}
}
return error;
}
LoadFromFile() to Read one VCalendar File
// read data from file
SFCError VCalendarFile::LoadFromFile(Void)
{
SFCError error;
SFXFile file;
SFXAnsiStringStreamReader reader;
UInt32 size;
SFXAnsiString string;
SFXPath filename(SFXPath(DIR_NAME + _fileName.Get()));
// Get file size
error = SFXFile::GetSize(filename, &size);
if (error == SFERR_NO_ERROR) {
// Open file
error = file.OpenReadOnly(filename);
if (error == SFERR_NO_ERROR) {
// Get stream for reading
error = file.GetStreamReader(size, &reader);
if (error == SFERR_NO_ERROR) {
reader.Fetch();
// Read from file
reader >> string;
}
file.Close();
}
}
if (error == SFERR_NO_ERROR) {
Import(string);
// Analyze data in vCalendar format
// Subsutitute each element into member variable
}
return error;
}







