// bdlt_timetableloader.h                                             -*-C++-*-
#ifndef INCLUDED_BDLT_TIMETABLELOADER
#define INCLUDED_BDLT_TIMETABLELOADER

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide a protocol (or pure interface) for loading timetables.
//
//@CLASSES:
//  bdlt::TimetableLoader: pure interface for loading timetables
//
//@SEE_ALSO: bdlt_timetablecache, 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:
// ```
// /// 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.
// class MyTimetableLoader : public bdlt::TimetableLoader {
//
//   public:
//     // CREATORS
//
//     /// Create a `MyTimetableLoader` object.
//     MyTimetableLoader();
//
//     /// Destroy this object.
//     virtual ~MyTimetableLoader();
//
//     // MANIPULATORS
//
//     /// 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.
//     virtual int load(bdlt::Timetable *result, const char *timetableName);
// };
// ```
// 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;
// }
// ```

#include <bdlscm_version.h>

namespace BloombergLP {
namespace bdlt {

class Timetable;

                          // =====================
                          // class TimetableLoader
                          // =====================

/// This class defines a protocol used to load timetables from a specific
/// source.  Each repository of timetable information can be supported by a
/// distinct implementation of this protocol.
class TimetableLoader {

  public:
    // CREATORS

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

    // MANIPULATORS

    /// 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.
    virtual int load(Timetable *result, const char *timetableName) = 0;
};

}  // close package namespace
}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
