Home > Products > SophiaFramework UNIVERSE > Tutorial > Scheduler > - 3 / 7 -

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.

  1. 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 ).
  2. Insert an element into _list with Insert() when the position is found
  3. Append an element at the end of _list with Append() if the position is not found
  4. Save the data with an inserted element as a file by using the SaveToFile() function of VCalendar
  5. 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;
}

Go back  1   2   3   4   5   6   Apdx   Next page