Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bdlt_timetableloader
[Package bdlt]

Provide a protocol (or pure interface) for loading timetables. More...

Namespaces

namespace  bdlt

Detailed Description

Outline
Purpose:
Provide a protocol (or pure interface) for loading timetables.
Classes:
bdlt::TimetableLoader pure interface for loading timetables
See also:
Component bdlt_timetablecache, Component bdlt_timetable
Description:
This component provides a protocol, bdlt::TimetableLoader, for loading timetables from a specific source. Each repository of timetable information can be supported by a distinct implementation of the TimetableLoader protocol. The protocol's primary method, load, loads a timetable into a bdlt::Timetable object. The timetable to load is identified by name, which is specified by a null-terminated C-style string (i.e., const char *).
Thread Safety:
Unless otherwise documented, a single timetable loader object is not safe for concurrent access by multiple threads. Classes derived from bdlt::TimetableLoader that are specifically designed for concurrent access must be documented as such. Unless specifically documented otherwise, separate objects of classes derived from bdlt::TimetableLoader may safely be used in separate threads.
Usage:
This section illustrates intended use of this component.
Example 1: Implementing the bdlt::TimetableLoader Protocol:
This example demonstrates an elided concrete implementation of the bdlt::TimetableLoader protocol that interprets timetable information contained in ASCII strings that are formatted using JSON. Note that, in general, an implementation of bdlt::TimetableLoader must obtain timetable information from some data source. Our elided implementation leaves it unspecified as to where the JSON strings are obtained (i.e., whether from a file system, a database, a local or remote service, etc.).
First, we show the JSON format that our timetable loader accepts:
  {
      "firstDate":             "YYYY-MM-DD",
      "lastDate":              "YYYY-MM-DD",
      "initialTransitionCode": code,
      "transitions":
        [
          {
            "datetime": "YYYY-MM-DDThh:mm:ss",
            "code":     code
          }
        ]
  }
Note that "YYYY-MM-DD" is an ISO 8601 representation for the value of a bdlt::Date object, "YYYY-MM-DDThh:mm:ss" is an ISO 8601 representation for the value of a bdlt::Datetime object, and code is an integer greater than or equal to -1 (with -1 used to specify bdlt::Timetable::k_UNSET_TRANSITION_CODE). We assume that the four JSON attributes, "firstDate", "lastDate", "initialTransitionCode", and "transitions", must occur in the JSON string in the order in which they appear in the above display, but only "firstDate" and "lastDate" are required attributes.
Then, we define the interface of our implementation:
  class MyTimetableLoader : public bdlt::TimetableLoader {
      // This class provides a concrete implementation of the
      // 'bdlt::TimetableLoader' protocol (an abstract interface) for loading
      // a timetable.  This elided implementation obtains timetable
      // information from ASCII strings formatted using JSON.  The source of
      // the strings is unspecified.

    public:
      // CREATORS
      MyTimetableLoader();
          // Create a 'MyTimetableLoader' object.

      virtual ~MyTimetableLoader();
          // Destroy this object.

      // MANIPULATORS
      virtual int load(bdlt::Timetable *result, const char *timetableName);
          // Load, into the specified 'result', the timetable identified by
          // the specified 'timetableName'.  Return 0 on success, and a
          // non-zero value otherwise.  If the timetable corresponding to
          // 'timetableName' is not found, 1 is returned with no effect on
          // '*result'.  If a non-zero value other than 1 is returned
          // (indicating a different error), '*result' is valid, but its
          // value is undefined.
  };
Next, we implement the creators, trivially, as MyTimetableLoader does not contain any instance data members:
  // CREATORS
  inline
  MyTimetableLoader::MyTimetableLoader()
  {
  }

  inline
  MyTimetableLoader::~MyTimetableLoader()
  {
  }
Then, we implement the load function:
  // MANIPULATORS
  int MyTimetableLoader::load(bdlt::Timetable *result,
                              const char      *timetableName)
  {
Next, we look up the timetable identified by timetableName and load the corresponding text into a bsl::string object, json (as stated earlier, we do not specify in this example from where the timetable information is obtained):
      // Obtain the information for the timetable identified by
      // 'timetableName' from an unspecified data source and load it into the
      // 'json' string.

      bsl::string json;

      // Since a JSON parser is not available to 'bdlt', this example assumes
      // that 'json' is populated with the following specific data:
      //..
      //  {
      //      "firstDate":             "2018-01-01",
      //      "lastDate":              "2018-12-31",
      //      "initialTransitionCode": 1,
      //      "transitions":
      //        [
      //          {
      //            "datetime": "2018-05-28T09:00:00",
      //            "code":     2
      //          },
      //          {
      //            "datetime": "2018-05-28T18:00:00",
      //            "code":     3
      //          }
      //        ]
      //  }
      //..
      // Similarly, we hard-wire the value of a status flag, 'rc', to
      // indicate that this string was successfully retrieved from the data
      // source.

      int rc = 0;  // success obtaining timetable information

      if (rc != 0) {
          return 1;                                                 // RETURN
      }
Note that the non-zero value 1 is returned only in the case where the timetable information corresponding to timetableName cannot be found (per the contract for the load method).
Then, we parse the "firstDate" and "lastDate" attributes from the json string, loading the results into like-named variables:
      // Parse the "firstDate" and "lastDate" JSON attributes and load the
      // results into 'firstDate' and 'lastDate', respectively.  It is an
      // error if either of the "firstDate" or "lastDate" attributes are
      // missing, or if they are out of order.

      bdlt::Date firstDate;
      bdlt::Date lastDate;

      // For the purposes of this Usage, we hard-wire the first and last
      // dates that are hypothetically parsed from the 'json' string, and
      // set the 'rc' status flag indicating that parsing succeeded.

      firstDate.setYearMonthDay(2018,  1,  1);
      lastDate.setYearMonthDay( 2018, 12, 31);
      rc = 0;  // success parsing "firstDate" and "lastDate" attributes

      if (rc != 0 || firstDate > lastDate) {
          return 2;                                                 // RETURN
      }

      result->reset();

      result->setValidRange(firstDate, lastDate);
Next, we parse the "initialTransitionCode" attribute from json:
      // For the purposes of this Usage, we hard-wire a boolean flag
      // indicating that the "initialTransitionCode" attribute was
      // hypothetically detected in the 'json' string.

      bool isInitialTransitionCodePresent = true;

      if (isInitialTransitionCodePresent) {

          // For the purposes of this Usage, we hard-wire the initial
          // transition code that is hypothetically parsed from the 'json'
          // string, and set the 'rc' status flag indicating that parsing
          // succeeded.

          int code = 1;

          rc = 0;  // success parsing "initialTransitionCode" attribute

          if (rc != 0) {
              return 3;                                             // RETURN
          }

          result->setInitialTransitionCode(code);
      }
Now, we parse the "transitions" attribute from json and load the result into a bsl::vector<bsl::pair<bdlt::Datetime, int> > object, transitions:
      // For the purposes of this Usage, we hard-wire a boolean flag
      // indicating that the "transitions" attribute was hypothetically
      // detected in the 'json' string.

      bool isTransitionsPresent = true;

      if (isTransitionsPresent) {

          // Parse the "transitions" JSON attribute and load 'transitions'
          // with the result.

          bsl::vector<bsl::pair<bdlt::Datetime, int> > transitions;

          // For the purposes of this Usage, we hard-wire the transitions
          // that are hypothetically parsed from the 'json' string, and set
          // the 'rc' status flag indicating that parsing succeeded.

          transitions.push_back(bsl::pair<bdlt::Datetime, int>(
                                        bdlt::Datetime(2018, 5, 28,  9), 2));
          transitions.push_back(bsl::pair<bdlt::Datetime, int>(
                                        bdlt::Datetime(2018, 5, 28, 18), 3));

          rc = 0;  // success parsing "transitions" attribute

          if (rc != 0) {
              return 4;                                             // RETURN
          }

          bsl::vector<bsl::pair<bdlt::Datetime, int> >::const_iterator it =
                                                         transitions.begin();

          while (it != transitions.end()) {
              const bdlt::Date& date = it->first.date();

              if (date < firstDate || date > lastDate || -1 > it->second) {
                  return 5;                                         // RETURN
              }

              result->addTransition(
                             it->first,
                             it->second >= 0
                                 ? it->second
                                 : bdlt::Timetable::k_UNSET_TRANSITION_CODE);

              ++it;
          }
      }
Our timetable loader imposes the requirement that the dates specified in the "transitions" JSON attribute must be within the range [firstDate .. lastDate] and the transition codes are non-negative or unset.
Finally, we return 0 indicating success:
      return 0;
  }