Chapters

 After the Psalm structures, the next important part of the day hours is the chapter.  Formally, the chapter is simply a short one-or-two-verse extract from scripture; in practice it is associated with a brief reponsory and (in the case of Lauds, Vespers and Compline) a hymn.  (The other lesser hours also have hymns but they stand in a position different from the chapter, earlier in the office.)  For the Triduum and in Easter Week there is no chapter.

The commonalities in this model are captured in the Chapter class, which is an abstract base class -- it defines the interface for but does not implement the formatting call for its contents.

class Chapter

{

protected:

  Chapter(const std::string &inText, const std::string &inSrc,

          std::span<std::string> inResponses)

      : m_chapterSrc(inSrc), m_chapterText(inText),

        m_responses(inResponses.begin(), inResponses.end()),

        m_sd(SpecialDays::NONE)

  { }

  explicit Chapter(const SpecialDays inSD) : m_responses{ "", "" }, m_sd(inSD)

  { }

  virtual ~Chapter();

public:

  // Needed in Eastertide to override ferial chapter with Sunday value

  void

  setChapter(const std::string &inText, const std::string &inSrc)

  {

    m_chapterText = inText;

    m_chapterSrc = inSrc;

  }

  virtual void formatChapter(const IEncapsulatedOfficeFormatter &inFormatter,

                             const IHymnSource &inHymns,

                             const HymnSeasons inSeason

                             = HymnSeasons::NORMAL) const = 0;


protected:

  std::string m_chapterSrc;

  std::string m_chapterText;

  mutable std::vector<std::string> m_responses;

  SpecialDays m_sd;

};

There are two intermediate forms derived from this class: the MinorHoursChapter (used for Prime, Terce, Sext, and None) and the MajorHoursChapter (used for Lauds, Vespers, and Compline).  The Major Hours chapter has an associated hymn that is missing from the MinorHoursChapter.

Minor Hours

Most of the logic associated with the chapters is actually involved in setting up the default texts for the "normal" days (not major feats).  As such, the intermediate class, MinorHoursChapter, has most of the logic that is then used by the derived classes. It also provides a mechanism for initializing in the initialization list in a constructor.

class MinorHoursChapter : public Chapter

{

public:

  class IInitializer {

  public:

    virtual ~IInitializer();

    virtual  std::string getText() const = 0;

    virtual  std::string getSrc() const = 0;

    virtual std::span<std::string> getResponses() const = 0;

    virtual bool isPassiontide() const = 0;

  };

  class NullInitializer: public IInitializer {

  public:

    virtual ~NullInitializer();

    virtual  std::string getText() const override { return {}; }

    virtual  std::string getSrc() const override { return {}; }

    virtual std::span<std::string> getResponses() const override;

    virtual bool isPassiontide() const override { return false; }

  };

  ~MinorHoursChapter() override;

protected:

  MinorHoursChapter(const std::string &inText, const std::string &inSrc,

                    std::span<std::string> inResponses,

                    const bool inIsPassiontide = false)

      : Chapter(inText, inSrc, inResponses), m_isPassiontide(inIsPassiontide)

  { }

  explicit MinorHoursChapter(const IInitializer& inInit)

    : MinorHoursChapter(inInit.getText(), inInit.getSrc(), inInit.getResponses(), inInit.isPassiontide())

  { }

  explicit MinorHoursChapter(const SpecialDays inSD)

      : Chapter(inSD), m_isPassiontide(inSD != SpecialDays::EASTER_WEEK)

  { }

public:

  const std::string& getChapterSrc() const { return m_chapterSrc; }

  const std::string& getChapterText() const { return m_chapterText; }

  const std::vector<std::string>& getChapterResponses() const { return m_responses; }

  bool empty() const { return m_chapterText.empty() && m_responses.empty(); }

  void formatChapter(const IEncapsulatedOfficeFormatter &inFormatter,

                const IHymnSource &inHymns,

                const HymnSeasons inSeason

                = HymnSeasons::NORMAL) const override;

private:

  bool m_isPassiontide;

};

Note the IInitializer class and its NullObject version.  The constructor using it uses the newish ability to delegate to another constructor.

The None Chapter shows how this is used at its simplest:

class NoneChapter : public MinorHoursChapter

{

public:

  explicit NoneChapter(const SpecialDays inSD) : MinorHoursChapter(inSD) {}

  NoneChapter(const std::string &inText, const std::string &inSrc,

               std::span<std::string> inResponses,

               const bool inPassiontide = false)

      : MinorHoursChapter(inText, inSrc, inResponses, inPassiontide)

  { }

  NoneChapter(const Grades inGrade, const HymnSeasons inSeason)

      : MinorHoursChapter(GetInitializer(inGrade, inSeason))

  { }

  explicit NoneChapter(const Days inDays)

      : MinorHoursChapter(GetGeneralInitializer(inDays))

  { }

  ~NoneChapter() override;

private:

  class PassiontideInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~PassiontideInitializer() override;

    std::string getText() const override;

    std::string getSrc() const override;

    std::span<std::string> getResponses() const override;

    bool

    isPassiontide() const override

    {

      return true;

    }

  };


  class AdventInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~AdventInitializer() override;

    std::string getText() const override;

    std::string getSrc() const override;

    std::span<std::string> getResponses() const override;

    bool

    isPassiontide() const override

    {

      return false;

    }

  };


  class ChristmasInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~ChristmasInitializer() override;

    std::string getText() const override;

    std::string getSrc() const override;

    std::span<std::string> getResponses() const override;

    bool

    isPassiontide() const override

    {

      return false;

    }

  };

  class LentInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~LentInitializer() override;

    std::string getText() const override;

    std::string getSrc() const override;

    std::span<std::string> getResponses() const override;

    bool

    isPassiontide() const override

    {

      return false;

    }

  };

  class MidLentInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~MidLentInitializer() override;

    std::string getText() const override;

    std::string getSrc() const override;

    std::span<std::string> getResponses() const override;

    bool

    isPassiontide() const override

    {

      return false;

    }

  };


  class EasterFeriaInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~EasterFeriaInitializer() override;

    std::string getText() const override;

    std::string getSrc() const override;

    std::span<std::string> getResponses() const override;

    bool

    isPassiontide() const override

    {

      return false;

    }

  };


  class SundayInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~SundayInitializer() override;

    std::string getText() const override;

    std::string getSrc() const override;

    std::span<std::string> getResponses() const override;

    bool

    isPassiontide() const override

    {

      return false;

    }

  };


  class EasterSundayInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~EasterSundayInitializer() override;

    std::string getText() const override;

    std::string getSrc() const override;

    std::span<std::string> getResponses() const override;

    bool

    isPassiontide() const override

    {

      return false;

    }

  };


  class FerialInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~FerialInitializer() override;

    std::string getText() const override;

    std::string getSrc() const override;

    std::span<std::string> getResponses() const override;

    bool

    isPassiontide() const override

    {

      return false;

    }

  };

  static const MinorHoursChapter::IInitializer &

  GetInitializer(const Grades inGrade, const HymnSeasons inSeason);


  static const MinorHoursChapter::IInitializer &

  GetGeneralInitializer(const Days inDays);

};

A typical initializer implementation looks like

std::string NoneChapter::PassiontideInitializer::getText() const

{

  return "And for this cause He is the Mediator of the new testament, that by means of death, for the redemption of the transgressions that were under the first testament, they which are called might receive the promise of eternal inheritance.";

}

std::string

NoneChapter::PassiontideInitializer::getSrc() const

{

  return "Heb ix";

}

std::span<std::string>

NoneChapter::PassiontideInitializer::getResponses() const

{

  static std::array<std::string, 4> responsories{

    "Nor my life with the blood-thirsty.",

    "O shut not up:* my soul with the sinners.",

    "Deliver me, Lord, from the evil man.",

    "And preserve me from the wicked man."

  };

  return responsories;

}

with different text for the differing contexts (nine of them).

The None chapter adds nothing except initialization to the MinorHoursChapter.  The two key functions are the two static Get...Initializer functions:

const MinorHoursChapter::IInitializer &

NoneChapter::GetInitializer(const Grades inGrade, const HymnSeasons inSeason)

{

  if (inSeason == HymnSeasons::ADVENT)

    {

      static AdventInitializer init;

      return init;

    }

  else if (inSeason == HymnSeasons::PASSIONTIDE)

    {

      static PassiontideInitializer init;

      return init;

    }

  else if (inSeason == HymnSeasons::INCARNATION)

    {

      static ChristmasInitializer init;

      return init;

    }

  else if (inSeason == HymnSeasons::LENT)

    {

      static LentInitializer init;

      return init;

    }

  else if (inSeason == HymnSeasons::MID_LENT)

    {

      static MidLentInitializer init;

      return init;

    }

  else if ((inSeason == HymnSeasons::EASTER)

           && ((inGrade == Grades::FERIA)

               || (inGrade == Grades::FESTAL_FERIA)))

    {

      static EasterFeriaInitializer init;

      return init;

    }

  else if ((inSeason == HymnSeasons::EASTER)

           && ((inGrade == Grades::DOMINICA)

               || (inGrade == Grades::DOMINICA_SECOND_CLASS)

               || (inGrade == Grades::DOMINICA_FIRST_CLASS)))

    {

      static EasterSundayInitializer init;

      return init;

    }

  else if ((inSeason == HymnSeasons::NORMAL)

           || (inSeason == HymnSeasons::SEPTUAGESIMA))

    {

      if ((inGrade == Grades::DOMINICA)

          || (inGrade == Grades::DOMINICA_SECOND_CLASS)

          || (inGrade == Grades::DOMINICA_FIRST_CLASS))

        {

          static SundayInitializer init;

          return init;

        }

      else if (inGrade == Grades::FERIA)

        {

          static FerialInitializer init;

          return init;

        }

    }

  {

    static BreviaryLib::MinorHoursChapter::NullInitializer init;

    return init;

  }

}


const MinorHoursChapter::IInitializer &

NoneChapter::GetGeneralInitializer(const BreviaryLib::Days inDays)

{

  if (inDays == BreviaryLib::Days::SUNDAY)

    {

      static SundayInitializer init;

      return init;

    }

  else

    {

      static FerialInitializer init;

      return init;

    }

}

There is, however, a small DRY problem.  Terce and Sext look exactly the same, except that they have different text for each of the nine defined initializers.  It would be nice to get the reduplication of the logic (textually almost exactly the same, but referencing different classes) eliminated.

We can do so by creating an object that handles already-defined initializers as references.  We can pass in the different initializers in various ways; I'm going to use a std::tuple, because that means a minimal degree of extra overhead.

class MinorHoursChapterInitializerHelper

{

public:

  MinorHoursChapterInitializerHelper(std::tuple<const MinorHoursChapter::IInitializer &,

     const MinorHoursChapter::IInitializer &,

     const MinorHoursChapter::IInitializer &,

     const MinorHoursChapter::IInitializer &,

     const MinorHoursChapter::IInitializer &,

     const MinorHoursChapter::IInitializer &,

     const MinorHoursChapter::IInitializer &,

     const MinorHoursChapter::IInitializer &,

     const MinorHoursChapter::IInitializer & > inVals):

    m_AdventInitializer(std::get<0>(inVals)),

    m_PassiontideInitializer(std::get<1>(inVals)),

    m_ChristmasInitializer(std::get<2>(inVals)),

    m_LentInitializer(std::get<3>(inVals)),

    m_MidLentInitializer(std::get<4>(inVals)),

    m_EasterFeriaInitializer(std::get<5>(inVals)),

    m_EasterSundayInitializer(std::get<6>(inVals)),

    m_SundayInitializer(std::get<7>(inVals)),

    m_FerialInitializer(std::get<8>(inVals))

  { }


  const MinorHoursChapter::IInitializer &

  getInitializer(const Grades inGrade, const HymnSeasons inSeason)

  {

    if (inSeason == HymnSeasons::ADVENT)

      {

return m_AdventInitializer;

      }

    else if (inSeason == HymnSeasons::PASSIONTIDE)

      {

return m_PassiontideInitializer;

      }

    else if (inSeason == HymnSeasons::INCARNATION)

      {

return m_ChristmasInitializer;

      }

    else if (inSeason == HymnSeasons::LENT)

      {

return m_LentInitializer;

      }

    else if (inSeason == HymnSeasons::MID_LENT)

      {

return m_MidLentInitializer;

      }

    else if ((inSeason == HymnSeasons::EASTER)

     && ((inGrade == Grades::FERIA)

|| (inGrade == Grades::FESTAL_FERIA)))

      {

return m_EasterFeriaInitializer;

      }

    else if ((inSeason == HymnSeasons::EASTER)

     && ((inGrade == Grades::DOMINICA)

|| (inGrade == Grades::DOMINICA_SECOND_CLASS)

|| (inGrade == Grades::DOMINICA_FIRST_CLASS)))

      {

return m_EasterSundayInitializer;

      }

    else if ((inSeason == HymnSeasons::NORMAL)

     || (inSeason == HymnSeasons::SEPTUAGESIMA))

      {

if ((inGrade == Grades::DOMINICA)

    || (inGrade == Grades::DOMINICA_SECOND_CLASS)

    || (inGrade == Grades::DOMINICA_FIRST_CLASS))

  {

    return m_SundayInitializer;

  }

else if (inGrade == Grades::FERIA)

  {

    return m_FerialInitializer;

  }

      }

    {

      static MinorHoursChapter::NullInitializer init;

      return init;

    }

  }


  const MinorHoursChapter::IInitializer &

  getGeneralInitializer(const Days inDays)

  {

    if (inDays == BreviaryLib::Days::SUNDAY)

      {

return m_SundayInitializer;

      }

    else

      {

return m_FerialInitializer;

      }

  }

  

private:


  const MinorHoursChapter::IInitializer & m_AdventInitializer;

  const MinorHoursChapter::IInitializer & m_PassiontideInitializer;

  const MinorHoursChapter::IInitializer & m_ChristmasInitializer;

  const MinorHoursChapter::IInitializer & m_LentInitializer;

  const MinorHoursChapter::IInitializer & m_MidLentInitializer;

  const MinorHoursChapter::IInitializer & m_EasterFeriaInitializer;

  const MinorHoursChapter::IInitializer & m_EasterSundayInitializer;

  const MinorHoursChapter::IInitializer & m_SundayInitializer;

  const MinorHoursChapter::IInitializer & m_FerialInitializer;

};

We have to ensure that all references are to static objects, and we have to force the std::make_tuple to make references by using std::cref:

namespace {

BreviaryLib::NoneChapter::AdventInitializer init1;

BreviaryLib::NoneChapter::PassiontideInitializer init2;

BreviaryLib::NoneChapter::ChristmasInitializer init3;

BreviaryLib::NoneChapter::LentInitializer init4;

BreviaryLib::NoneChapter::MidLentInitializer init5;

BreviaryLib::NoneChapter::EasterFeriaInitializer init6;

BreviaryLib::NoneChapter::EasterSundayInitializer init7;

BreviaryLib::NoneChapter::SundayInitializer init8;

BreviaryLib::NoneChapter::FerialInitializer init9;

auto InitArgs = std::make_tuple<>( std::cref(init1),

   std::cref(init2),

   std::cref(init3),

   std::cref(init4),

   std::cref(init5),

   std::cref(init6),

   std::cref(init7),

   std::cref(init8),

   std::cref(init9));


BreviaryLib::MinorHoursChapterInitializerHelper theHelper(InitArgs);

}

(We also have to make the initializers public to allow them to be created as above in the anonymous namespace as implementation details.)  Our two static functions remain private, but are now defined as:

const BreviaryLib::MinorHoursChapter::IInitializer &

NoneChapter::GetInitializer(const Grades inGrade, const HymnSeasons inSeason)

{

  return theHelper.getInitializer(inGrade, inSeason);

}

const BreviaryLib::MinorHoursChapter::IInitializer &

NoneChapter::GetGeneralInitializer(const BreviaryLib::Days inDays)

{

  return theHelper.getGeneralInitializer(inDays);

}

The PrimeChapter is also derived from the MinorHoursChapter, but its pattern does not match that of the three other minor hours, and is far simpler:

class PrimeChapter : public MinorHoursChapter

{

public:

  ~PrimeChapter() override;

  PrimeChapter(const std::string &inText, const std::string &inSrc,

               std::span<std::string> inResponses,

               const bool inIsPassiontide = false)

      : MinorHoursChapter(inText, inSrc, inResponses, inIsPassiontide)

  { }

  explicit PrimeChapter(const SpecialDays inSD) : MinorHoursChapter(inSD) {}

  PrimeChapter(const Grades inGrade, const HymnSeasons inSeason,

               const bool inIsMarian)

      : MinorHoursChapter(GetInitializer(inGrade, inSeason, inIsMarian))

  { }


private:

  static const MinorHoursChapter::IInitializer &

  GetInitializer(const Grades inGrade, const HymnSeasons inSeason,

                 const bool inIsMarian);

  class PassiontideInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~PassiontideInitializer() override;

    std::string getText() const override

    {

      return "Love the truth and peace. Thus saith the Lord of Hosts.";

    }

    std::string getSrc() const override

    {

      return "Zech. viii";

    }

    std::span<std::string> getResponses() const override

    {

      static std::array<std::string, 2> rval

          = { "O Lord, arise, help us",

              "And deliver us for Thy Name's sake." };

      return rval;

    }

    bool isPassiontide() const override

    {

      return true;

    }

  };

  class FeriaInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    ~FeriaInitializer() override;

    std::string getText() const override

    {

      return "Love the truth and peace. Thus saith the Lord of Hosts.";

    }

    std::string getSrc() const override

    {

      return "Zech. viii";

    }

    std::span<std::string> getResponses() const override;

    bool isPassiontide() const override

    {

      return false;

    }

  };

  class FestalFeriaInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    FestalFeriaInitializer(const bool inIsEaster, const bool inIsAscension)

        : m_isEaster(inIsEaster), m_isAscension(inIsAscension)

    { }

    ~FestalFeriaInitializer() override;

    std::string getText() const override

    {

      return "O Lord, be gracious unto us, we have waited for Thee : be Thou our arm every morning, our salvation also in the time of trouble.";

    }

    std::string getSrc() const override

    {

      return "Isa. xxxiii";

    }

    std::span<std::string> getResponses() const override;


    bool isPassiontide() const override

    {

      return false;

    }

  private:

    bool m_isEaster;

    bool m_isAscension;

  };


  class FestalInitializer : public MinorHoursChapter::IInitializer

  {

  public:

    FestalInitializer(const bool inIsEaster, const bool inIsAscension,

                      const bool inIsMarian)

        : m_isEaster(inIsEaster), m_isAscension(inIsAscension),

          m_isMarian(inIsMarian)

    { }


    ~FestalInitializer() override;

    std::string

    getText() const override

    {

      return "Now unto the King Eternal, Immortal, Invisible, the only wise God, be honour and glory for ever and ever. Amen.";

    }

    std::string getSrc() const override

    {

      return "I Tim. i";

    }

    std::span<std::string> getResponses() const override;

    bool isPassiontide() const override

    {

      return false;

    }

  private:

    bool m_isEaster;

    bool m_isAscension;

    bool m_isMarian;

  };

};

The single GetInitializer() call has fewer things to juggle:

const MinorHoursChapter::IInitializer &

PrimeChapter::GetInitializer(const Grades inGrade, const HymnSeasons inSeason,

     const bool inIsMarian) {


  if (inSeason == HymnSeasons::PASSIONTIDE)

    {

      static PassiontideInitializer init;

      return init;

    }

  else if (inSeason == HymnSeasons::EASTER)

    {

      if (inGrade >= Grades::GREATER_SIMPLE)

{

  if (inIsMarian)

    {

      static FestalInitializer init(true, false, true);

      return init;

    }

  else

    {

      static FestalInitializer init(true, false, false);

      return init;

    }

}

      else

{

  static FestalFeriaInitializer init(true, false);

  return init;

}

    }

  else if (inSeason == HymnSeasons::ASCENSION)

    {

      if (inGrade >= Grades::GREATER_SIMPLE)

{

  if (inIsMarian)

    {

      static FestalInitializer init(false, true, true);

      return init;

    }

  else

    {

      static FestalInitializer init(false, true, false);

      return init;

    }

}

      else

{

  static FestalFeriaInitializer init(false, true);

  return init;

}

    }

  else

    {

      bool Festal = ((inSeason == HymnSeasons::INCARNATION) || (inSeason == HymnSeasons::PENTECOST));

    

      if (inGrade >= Grades::GREATER_SIMPLE)

{

  if (inIsMarian)

    {

      static FestalInitializer init(false, false, true);

      return init;

    }

  else

    {

      static FestalInitializer init(false, false, false);

      return init;

    }

}

      else if ((inGrade == Grades::FERIA) && !Festal)

{

  static FeriaInitializer init;

  return init;   

}

      else

{

  static FestalFeriaInitializer init(false, false);

  return init;

}

    }

}


Note that we can't just do

      if (inGrade >= Grades::GREATER_SIMPLE)

{

            static FestalInitializer init(false, false, inIsMarian);

    return init;

}

because if the next call has a different value for isMarian the original value would be frozen into the returned object.

Major Hours Chapters

For Lauds, Vespers, and Compline there is a hymn associated with the chapter complex.  There is, accordingly, a shared implementation for the three offices:

class MajorHoursChapter : public Chapter

{

public:

  ~MajorHoursChapter() override;


protected:

  class Initializer

  {

  public:

    virtual ~Initializer();

    virtual const std::string &getText() const = 0;

    virtual const std::string &getSrc() const = 0;

    virtual std::span<std::string> getResponses() const = 0;

    virtual const std::string &getHymn() const = 0;

  };


  class NullInitializer: public Initializer

  {

  public:

    ~NullInitializer() override;

    const std::string &getText() const override { return m_nullrval; }

    const std::string &getSrc() const override { return m_nullrval; }

    std::span<std::string> getResponses() const override { return m_nullvect; }

    const std::string &getHymn() const override { return m_nullrval; }

  private:

    std::string m_nullrval;

    mutable std::vector<std::string> m_nullvect;

  };


   MajorHoursChapter(const std::string &inText, const std::string &inSrc,

                    std::span<std::string> inResponses,

                    const std::string &inHymn)

      : Chapter(inText, inSrc, inResponses), m_hymnName(inHymn)

  { }


  explicit MajorHoursChapter(const Initializer &inInit)

    : MajorHoursChapter(inInit.getText(), inInit.getSrc(), inInit.getResponses(),

inInit.getHymn())

  { }


  explicit MajorHoursChapter(SpecialDays inSD) : Chapter(inSD) {}


  void formatHymn(const IEncapsulatedOfficeFormatter &inFormatter,

                  const IHymnSource &inHymns,

                  const HymnSeasons inSeason) const;


public:

  void formatChapter(const IEncapsulatedOfficeFormatter &inFormatter,

                     const IHymnSource &inHymns,

                     const HymnSeasons inSeason

                     = HymnSeasons::NORMAL) const override;


protected:

  std::string m_hymnName;

};


The two core functions for formatting are straightforward:

void MajorHoursChapter::formatHymn(const IEncapsulatedOfficeFormatter &inFormatter,

                              const IHymnSource &inHymns,

                              const HymnSeasons inSeason) const

{

  inFormatter.formatHymn(inHymns.getHymn(m_hymnName, inSeason), m_hymnName);

}

void MajorHoursChapter::formatChapter(

    const IEncapsulatedOfficeFormatter &inFormatter,

    const IHymnSource &inHymns, const HymnSeasons inSeason) const

{

  inFormatter.formatChapter(m_chapterText, m_chapterSrc);

  formatHymn(inFormatter, inHymns, inSeason);

  if (m_responses.size() >= 2)

    inFormatter.formatResponsory(m_responses[0], m_responses[1],

                                 (inSeason == HymnSeasons::EASTER));

}

For Lauds and Vespers, the chapter texts can vary with each feat or major Sunday, so the only general initializers are for the simplest  Sundays and for ferias.  Thus, most simply, for Lauds:

class LaudsChapter : public MajorHoursChapter, public ILaudsChapter

{

public:


  LaudsChapter(): MajorHoursChapter(MajorHoursChapter::NullInitializer())  { }


  ~LaudsChapter() override;


  LaudsChapter(const Days inDays, const IHoursInfo &inHoursInfo)

      : MajorHoursChapter(GetInitializer(inDays, inHoursInfo))

  {

  }


  LaudsChapter(const std::string &inText, const std::string &inSrc,

               std::span<std::string> inResponses, const std::string &inHymn)

      : MajorHoursChapter(inText, inSrc, inResponses, inHymn)

  {

  }


  explicit LaudsChapter(const SpecialDays inSD) : MajorHoursChapter(inSD)

  {

    if (inSD == SpecialDays::EASTER_WEEK)

      {

        m_responses[0] = "The Lord is risen from the sepulchre";

        m_responses[1] = "Who for our sakes did hang upon the tree, alleluia";

      }

  }


  std::span<std::string> getResponses() const override { return m_responses; }


  const std::string & getChapterSrc() const override { return m_chapterSrc; }


  const std::string & getChapterText() const override { return m_chapterText; }


  const std::string & getHymnName() const override { return m_hymnName; }


private:

  class SundayInitializer : public MajorHoursChapter::Initializer

  {

  public:

    explicit SundayInitializer(const IHoursInfo &inHoursInfo);


    ~SundayInitializer() override;


    const std::string &

    getText() const override

    {

      return m_text;

    }

    const std::string &

    getSrc() const override

    {

      return m_src;

    }

    std::span<std::string>

    getResponses() const override

    {

      return m_responses;

    }

    const std::string &

    getHymn() const override

    {

      return m_hymn;

    }


    void reset(const IHoursInfo &inHoursInfo);


  private:

    std::string m_hymn;

    std::string m_text{

      "Blessing, and glory, and wisdom, and thanksgiving, and honour, and power, and might, be unto our God for ever and ever. Amen."

    };

    std::string m_src{ "Rev. vii" };

    mutable std::array<std::string, 2> m_responses{

      "The Lord is King", "He hath put on glorious apparel, alleluia"

    };

  };


  class FerialInitializer : public MajorHoursChapter::Initializer

  {

  public:

    FerialInitializer(const Days inDays, const IHoursInfo &inHoursInfo);

    ~FerialInitializer() override;

    const std::string & getText() const override

    {

      return m_text;

    }

    const std::string & getSrc() const override

    {

      return m_src;

    }

    std::span<std::string> getResponses() const override

    {

      return m_responses;

    }

    const std::string & getHymn() const override

    {

      return m_hymn;

    }

    void reset(const Days inDays, const IHoursInfo &inHoursInfo);

  private:

    std::string m_hymn;

    std::string m_text{

      "Watch ye, stand fast in the faith, quit you like men, be strong. Let all your things be done with charity."

    };

    std::string m_src{ "I Cor. xvi" };

    mutable std::array<std::string, 2> m_responses{

      "Have I not thought upon Thee when I was waking?",

      "Because Thou hast been my helper." };

    };


    static const MajorHoursChapter::Initializer &

    GetInitializer(const Days inDays, const IHoursInfo &inHoursInfo);

  };

The GetInitializer() static function simplifies by using one Ferial and one Sunday initializer; this requires that values can be reset on subsequent calls:

const MajorHoursChapter::Initializer &

LaudsChapter::GetInitializer(const Days inDays, const IHoursInfo &inHoursInfo)

{

  static FerialInitializer frval(inDays, inHoursInfo);

  static SundayInitializer srval(inHoursInfo);

  switch (inDays)

    {

      using enum Days;

    case SUNDAY:

      {

        srval.reset(inHoursInfo);

        return srval;

      }

      break;

    case MONDAY:

      [[fallthrough]];

    case TUESDAY:

      [[fallthrough]];

    case WEDNESDAY:

      [[fallthrough]];

    case THURSDAY:

      [[fallthrough]];

    case FRIDAY:

      [[fallthrough]];

    case SATURDAY:

      {

frval.reset(inDays, inHoursInfo);

        return frval;

      }

    default:

      srval.reset(inHoursInfo);

      return srval;

    }

}


As this library is not designed for multithreaded use, this is safe. (To do otherwise, given the possible variation in the inHoursInfo data, would have required a complete revamp of the signatures.)

The Vespers model is similar, though it has a few extra tweaks to manage a peculiarity of the Hymns for Apostles -- this will be looked at later when we look at the overall Hymns model.

Compline has a small set of hymns which are used nowhere else and are completely determined by season, for the Sarum use, and one hymn only, for Roman use.  It implements the IHymnSource interface (also to be covered later) and calls to format the chapter reference it twice, once as the calling class and once as the hymn source.

class ComplineChapter : public IHymnSource, public MajorHoursChapter

{

public:

  ~ComplineChapter() override;


  ComplineChapter(const Grades inGrade, const HymnSeasons inSeason,

                  const bool inUseRomanUse);


  explicit ComplineChapter(const SpecialDays inDay) : MajorHoursChapter(inDay) {}


  void

  formatChapter(const IEncapsulatedOfficeFormatter &inFormatter,

                const IHymnSource &inHymns,

                const HymnSeasons inSeason

                = HymnSeasons::NORMAL) const override

  {

    if (m_sd == SpecialDays::NONE)

      MajorHoursChapter::formatChapter(inFormatter, *this, inSeason);

  }


  std::string getHymn(const std::string& inName, const HymnSeasons inSeason) const override;

  

  std::string getAnnueChriste(const std::string &inInterpolatedVerse,

      const bool inIsPlural) const override { return {}; }


  static std::string GetHymnName(const BreviaryLib::Grades inGrade, const BreviaryLib::HymnSeasons inSeason,

const bool inUseRomanUse);

  

private:

  Doxologies m_doxologies;

};

The Sarum-versus-Roman logic can be seen in:

std::string ComplineChapter::GetHymnName(const BreviaryLib::Grades inGrade,

                             const BreviaryLib::HymnSeasons inSeason,

                             const bool inUseRomanUse)

{

  if (inUseRomanUse

      || ((inSeason == BreviaryLib::HymnSeasons::NORMAL)

          && ((inGrade == BreviaryLib::Grades::FERIA)

              || (inGrade == BreviaryLib::Grades::LESSER_OCTAVE)

              || (inGrade == BreviaryLib::Grades::SIMPLE)

              || (inGrade == BreviaryLib::Grades::DOMINICA)

              || (inGrade == BreviaryLib::Grades::DOMINICA_SECOND_CLASS)

              || (inGrade == BreviaryLib::Grades::DOMINICA_FIRST_CLASS))))

    {

      return "Te lucis ante terminum"s;

    }

  else if ((inSeason == BreviaryLib::HymnSeasons::NORMAL)

           && ((inGrade == BreviaryLib::Grades::GREATER_OCTAVE)

               || (inGrade == BreviaryLib::Grades::OCTAVE_DAY)

               || (inGrade == BreviaryLib::Grades::DOUBLE)

               || (inGrade == BreviaryLib::Grades::DOUBLE_SECOND_CLASS)

               || (inGrade == BreviaryLib::Grades::DOUBLE_FIRST_CLASS)))

    {

      return "Salvator mundi"s;

    }

  else if (inSeason == BreviaryLib::HymnSeasons::INCARNATION)

    {

      // Actually use of York, not Sarum...

      return "Corde natus ex parentis"s;

    }

  else if ((inSeason == BreviaryLib::HymnSeasons::LENT)

           || (inSeason == BreviaryLib::HymnSeasons::MID_LENT))

    {

      return "Christe qui lux es et dies"s;

    }

  else if (inSeason == BreviaryLib::HymnSeasons::PASSIONTIDE)

    {

      return "Cultor Dei"s;

    }

  else if (inSeason == BreviaryLib::HymnSeasons::EASTER)

    {

      return "Jesu Salvator saeculi"s;

    }

  else if (inSeason == BreviaryLib::HymnSeasons::ASCENSION)

    {

      return "Jesu nostra Redemptio"s;

    }

  else if (inSeason == BreviaryLib::HymnSeasons::PENTECOST)

    {

      return "Veni Sancte Spiritus"s;

    }

  else

    return "Te lucis ante terminum"s;

}


Comments

Popular posts from this blog

LT Project: Author

Boundaries

Decent First Drafts