// bdlt_calendarloader.h                                              -*-C++-*-
#ifndef INCLUDED_BDLT_CALENDARLOADER
#define INCLUDED_BDLT_CALENDARLOADER

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

//@PURPOSE: Provide a protocol (or pure interface) for loading calendars.
//
//@CLASSES:
//  bdlt::CalendarLoader: pure interface for loading calendars
//
//@SEE_ALSO: bdlt_calendarcache, bdlt_packedcalendar
//
//@DESCRIPTION: This component provides a protocol, 'bdlt::CalendarLoader', for
// loading calendars from a specific source.  Each repository of calendar
// information can be supported by a distinct implementation of the
// 'CalendarLoader' protocol.  The protocol's primary method, 'load', loads a
// calendar into a 'bdlt::PackedCalendar' object.  The calendar 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 calendar loader object is not safe for
// concurrent access by multiple threads.  Classes derived from
// 'bdlt::CalendarLoader' that are specifically designed for concurrent access
// must be documented as such.  Unless specifically documented otherwise,
// separate objects of classes derived from 'bdlt::CalendarLoader' may safely
// be used in separate threads.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Implementing the 'bdlt::CalendarLoader' Protocol
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This example demonstrates an elided concrete implementation of the
// 'bdlt::CalendarLoader' protocol that interprets calendar information
// contained in ASCII strings that are formatted using JSON.  Note that, in
// general, an implementation of 'bdlt::CalendarLoader' must obtain calendar
// 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 calendar loader accepts.  For
// simplicity, we omit support for holiday codes and weekend-days transitions:
//..
//  {
//      "firstDate":   "YYYY-MM-DD",
//      "lastDate":    "YYYY-MM-DD",
//      "weekendDays": [ wd, ... ],
//      "holidays":    [ "YYYY-MM-DD", ... ]
//  }
//..
// Note that "YYYY-MM-DD" is an ISO 8601 representation for the value of a
// 'bdlt::Date' object and 'wd' is an integer in the range '[1 .. 7]'.  The
// range used for specifying weekend days corresponds directly to the
// 'bdlt::DayOfWeek::Enum' enumeration, '[e_SUN = 1 .. e_SAT]' (see
// 'bdlt_dayofweek').  We assume that the four JSON attributes, "firstDate",
// "lastDate", "weekendDays", and "holidays", 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 MyCalendarLoader : public bdlt::CalendarLoader {
//      // This class provides a concrete implementation of the
//      // 'bdlt::CalendarLoader' protocol (an abstract interface) for loading
//      // a calendar.  This elided implementation obtains calendar information
//      // from ASCII strings formatted using JSON.  The source of the strings
//      // is unspecified.
//
//    public:
//      // CREATORS
//      MyCalendarLoader();
//          // Create a 'MyCalendarLoader' object.
//
//      virtual ~MyCalendarLoader();
//          // Destroy this object.
//
//      // MANIPULATORS
//      virtual int load(bdlt::PackedCalendar *result,
//                       const char           *calendarName);
//          // Load, into the specified 'result', the calendar identified by
//          // the specified 'calendarName'.  Return 0 on success, and a
//          // non-zero value otherwise.  If the calendar corresponding to
//          // 'calendarName' 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 'MyCalendarLoader' does not
// contain any instance data members:
//..
//  // CREATORS
//  inline
//  MyCalendarLoader::MyCalendarLoader()
//  {
//  }
//
//  inline
//  MyCalendarLoader::~MyCalendarLoader()
//  {
//  }
//..
// Then, we implement the 'load' function:
//..
//  // MANIPULATORS
//  int MyCalendarLoader::load(bdlt::PackedCalendar *result,
//                             const char           *calendarName)
//  {
//..
// Next, we look up the calendar identified by 'calendarName' and load the
// corresponding text into a 'bsl::string' object, 'json' (as stated earlier,
// we do not specify in this example from where the calendar information is
// obtained):
//..
//      // Obtain the information for the calendar identified by 'calendarName'
//      // 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":   "1990-01-01",
//      //      "lastDate":    "1990-12-31",
//      //      "weekendDays": [ 1, 7 ],
//      //      "holidays":    [ "1990-05-28", "1990-07-04", "1990-09-03" ]
//      //  }
//      //..
//      // 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 calendar information
//
//      if (rc != 0) {
//          return 1;                                                 // RETURN
//      }
//..
// Note that the non-zero value 1 is returned only in the case where the
// calendar information corresponding to 'calendarName' 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(1990,  1,  1);
//      lastDate.setYearMonthDay( 1990, 12, 31);
//      rc = 0;  // success parsing "firstDate" and "lastDate" attributes
//
//      if (rc != 0 || firstDate > lastDate) {
//          return 2;                                                 // RETURN
//      }
//
//      result->removeAll();
//
//      result->setValidRange(firstDate, lastDate);
//..
// Next, we parse the "weekendDays" attribute from 'json' and load the result
// into a 'bdlt::DayOfWeekSet' object, 'dayOfWeekSet':
//..
//      // For the purposes of this Usage, we hard-wire a boolean flag
//      // indicating that the "weekendDays" attribute was hypothetically
//      // detected in the 'json' string.
//
//      bool isWeekendDaysAttributePresent = true;
//
//      if (isWeekendDaysAttributePresent) {
//
//          // Parse the "weekendDays" JSON attribute and load 'dayOfWeekSet'
//          // with the result.
//
//          bdlt::DayOfWeekSet dayOfWeekSet;
//
//          // For the purposes of this Usage, we hard-wire the weekend days
//          // that are hypothetically parsed from the 'json' string, and set
//          // the 'rc' status flag indicating that parsing succeeded.
//
//          dayOfWeekSet.add(bdlt::DayOfWeek::e_SUN);
//          dayOfWeekSet.add(bdlt::DayOfWeek::e_SAT);
//          rc = 0;  // success parsing "weekendDays" attribute
//
//          if (rc != 0) {
//              return 3;                                             // RETURN
//          }
//
//          result->addWeekendDays(dayOfWeekSet);
//      }
//..
// Now, we parse the "holidays" attribute from 'json' and load the result into
// a 'bsl::vector<bdlt::Date>' object, 'holidays':
//..
//      // For the purposes of this Usage, we hard-wire a boolean flag
//      // indicating that the "holidays" attribute was hypothetically detected
//      // in the 'json' string.
//
//      bool isHolidaysAttributePresent = true;
//
//      if (isHolidaysAttributePresent) {
//
//          // Parse the "holidays" JSON attribute and load 'holidays' with the
//          // result.
//
//          bsl::vector<bdlt::Date> holidays;
//
//          // For the purposes of this Usage, we hard-wire the holidays that
//          // are hypothetically parsed from the 'json' string, and set the
//          // 'rc' status flag indicating that parsing succeeded.
//
//          holidays.push_back(bdlt::Date(1990,  5, 28));  // Memorial Day
//          holidays.push_back(bdlt::Date(1990,  7,  4));  // Independence Day
//          holidays.push_back(bdlt::Date(1990,  9,  3));  // Labor Day
//          rc = 0;  // success parsing "holidays" attribute
//
//          if (rc != 0) {
//              return 4;                                             // RETURN
//          }
//
//          bsl::vector<bdlt::Date>::const_iterator it = holidays.begin();
//
//          while (it != holidays.end()) {
//              const bdlt::Date& holiday = *it;
//
//              if (holiday < firstDate || holiday > lastDate) {
//                  return 5;                                         // RETURN
//              }
//
//              result->addHoliday(holiday);
//
//              ++it;
//          }
//      }
//..
// Note that the 'addHoliday' method can extend the range of the calendar.  Our
// calendar loader instead imposes the requirement that the dates specified in
// the "holidays" JSON attribute must be within the range
// '[firstDate .. lastDate]'.
//
// Finally, we return 0 indicating success:
//..
//      return 0;
//  }
//..

#include <bdlscm_version.h>

namespace BloombergLP {
namespace bdlt {

class PackedCalendar;

                         // ====================
                         // class CalendarLoader
                         // ====================

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

  public:
    // CREATORS
    virtual ~CalendarLoader();
        // Destroy this object.

    // MANIPULATORS
    virtual int load(PackedCalendar *result, const char *calendarName) = 0;
        // Load, into the specified 'result', the calendar identified by the
        // specified 'calendarName'.  Return 0 on success, and a non-zero value
        // otherwise.  If the calendar corresponding to 'calendarName' 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.
};

}  // 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 ----------------------------------