Prime and Compline

 Prime

Like the three standard lesser hours, Prime is derived from LesserHoursBase.  There are a couple of minor differences from the three simple offices, though.

Prime's content is heavily determined by the day of the week (unlike the three lesser hours, which vary primarily with Sunday) and less frequently determined by feast-days.  Like Compline, it never uses the collect of the day.

In the Sarum use, the collect changes if the day is a feast; in the Roman use, it is unchanging.  (In Roman use Prime is also followed immediately by the Martyrology.  My code does not support the Martyrology, as I don't have the data necessary for it.)

So the construction pattern is a little different, and the class has static members for the collects:

class Prime : private LesserHourBase, public boost::noncopyable

{

public:

  Prime(const IHoursInfo &inInfo, const IPrimeInfo &inPrimeInfo);

  Prime(const IPsalter &inPsalter, const Days inDays,

        const HymnSeasons inSeason, const Grades inGrade,

        const bool inIsMarian, const bool inIsRomanUse):

      LesserHourBase(

          inDays,

          ((static_cast<int>(inGrade) >= static_cast<int>(Grades::DOUBLE) && ! inIsRomanUse)

               ? s_DoubleCollect

               : s_Collect),

          OfficeNames::PRIME),

      m_antiphons(inSeason), m_psalms(inPsalter, inDays, inSeason),

      m_chapter(inGrade, inSeason, inIsMarian)

  { }


  Prime(const IPsalter &inPsalter, const SpecialDays inDay):

      LesserHourBase(inDay), m_antiphons(inDay),

      m_psalms(inPsalter, inDay, Days::SUNDAY), m_chapter(inDay)

  { }

  ~Prime() override;

  void formatOffice(const IEncapsulatedOfficeFormatter &inFormatter,

                    const IPsalter &inPsalter, const bool inRomanUse,

                    const bool inIsPriest, const IHymnSource &inHymns) const

  {

    formatOfficeImpl(inFormatter, inPsalter, inRomanUse, inIsPriest, inHymns,

                     m_psalms, m_chapter, m_antiphons);

  }

private:

  std::string getHymnName() const override { return "Iam lucis ordo sidere"; }


  std::string getOfficeName() const override { return "PRIME"; }


  PrimeAntiphons m_antiphons;

  PrimePsalmSpec m_psalms;

  PrimeChapter m_chapter;

  static inline std::string s_Collect{

    "O LORD, our heavenly Father, Almighty and everlasting God, Who hast safely brought us to the beginning of this day ; defend us in the same with Thy mighty power; and grant that this day we fall into no sin, neither run into any kind of danger ; but that all our doings may be ordered by Thy governance, to do always that is righteous in Thy sight; through Jesus Christ our Lord : Who liveth. Amen."

  };

  static inline std::string s_DoubleCollect{

    "In this hour of this day, fill us, Lord, with Thy mercy; that going forth in Thy strength, we may make our boast of Thee all the day long; through Jesus Christ our Lord : Who liveth. Amen."

  };

};


Compline

Compline is not derived from the LesserHourBase, but it is in some ways like Prime; its collect is not dependent on the Sunday or feast day collect, and it varies by Roman or Sarum use.  However, its structure is not like any other office very closely.  It also has significantly more high-level variances based on Roman or Sarum Use than any other office: accordingly we use a strategy here to organize the variant logic.

class Compline : public boost::noncopyable

{

public:

  class IUseHandler

  {

  public:

    virtual ~IUseHandler();


    virtual void formatEasterInvocation(

        const IEncapsulatedOfficeFormatter &inFormatter) const = 0;

    virtual void formatIntroductoryChapter(

        const IEncapsulatedOfficeFormatter &inFormatter) const = 0;

    virtual void formatMedialConfiteor(

        const IEncapsulatedOfficeFormatter &inFormatter) const = 0;

    virtual void formatPenitentialPsalm(

        const FerialPetitions &inPenitentialPsalm, const IPsalter &inPsalter,

        const IEncapsulatedOfficeFormatter &inFormatter) const = 0;

    virtual void

    formatCollect(const IEncapsulatedOfficeFormatter &inFormatter) const = 0;

  };

  class SarumUseHandler : public IUseHandler

  {

  public:

    ~SarumUseHandler() override;

    void formatEasterInvocation(

        const IEncapsulatedOfficeFormatter &inFormatter) const override;

    void formatIntroductoryChapter(

        const IEncapsulatedOfficeFormatter &inFormatter) const override;

    void formatMedialConfiteor(

        const IEncapsulatedOfficeFormatter &inFormatter) const override;

    void formatPenitentialPsalm(

        const FerialPetitions &inPenitentialPsalm, const IPsalter &inPsalter,

        const IEncapsulatedOfficeFormatter &inFormatter) const override;

    void formatCollect(

        const IEncapsulatedOfficeFormatter &inFormatter) const override;

  };

  class RomanUseHandler : public IUseHandler

  {

  public:

    ~RomanUseHandler() override;

    void formatEasterInvocation(

        const IEncapsulatedOfficeFormatter &inFormatter) const override;

    void formatIntroductoryChapter(

        const IEncapsulatedOfficeFormatter &inFormatter) const override;

    void formatMedialConfiteor(

        const IEncapsulatedOfficeFormatter &inFormatter) const override;

    void formatPenitentialPsalm(

        const FerialPetitions &inPenitentialPsalm, const IPsalter &inPsalter,

        const IEncapsulatedOfficeFormatter &inFormatter) const override;

    void formatCollect(

        const IEncapsulatedOfficeFormatter &inFormatter) const override;

  };

  enum class SpecialAntiphonDays

  {

    CHRISTMAS_EVE,

    EPIPHANY,

    CANDLEMAS,

    HOLY_NAME

  };

  Compline(const SpecialDays inSpecialDay, const IPsalter &inPsalter,

           const bool inFollowRomanUse):

      m_useHandler(CreateUseHandler(inFollowRomanUse)),

      m_antiphons(inSpecialDay), m_chapter(inSpecialDay),

      m_NDAntiphons(inSpecialDay, inPsalter),

      m_penitentialPsalms(inSpecialDay), m_season(HymnSeasons::PASSIONTIDE),

      m_specialDay(inSpecialDay)

  { }


  Compline(const HymnSeasons inSeason, const Grades inGrade,

           const bool inUseRomanUse):

      m_useHandler(CreateUseHandler(inUseRomanUse)),

      m_antiphons(inSeason), m_chapter(inGrade, inSeason, inUseRomanUse),

      m_NDAntiphons(inSeason, inUseRomanUse),

      m_penitentialPsalms(inGrade, Days::MONDAY, inSeason,

                          OfficeNames::COMPLINE),

      m_season(inSeason), m_specialDay(SpecialDays::NONE)

  { }

  Compline(const IHoursInfo &inInfo, const IComplineInfo &inComplineInfo);


  explicit Compline(const SpecialAntiphonDays inDay);


  void formatOffice(const IEncapsulatedOfficeFormatter &inFormatter,

                    const IPsalter &inPsalter, const bool inIsPriest,

                    const IHymnSource &inHymns);


private:

  static std::unique_ptr<IUseHandler> CreateUseHandler(const bool inVal)

  {

    if (inVal)

      return std::make_unique<RomanUseHandler>();

    return std::make_unique<SarumUseHandler>();

  }


  std::unique_ptr<IUseHandler> m_useHandler;

  ComplineAntiphons m_antiphons;

  ComplineChapter m_chapter;

  NuncDimittisAntiphons m_NDAntiphons;

  ComplinePsalmSpec m_psalms;

  FerialPetitions m_penitentialPsalms;

  HymnSeasons m_season;

  SpecialDays m_specialDay;


  class SpecialAntiphonInitializer

  {

  public:

    std::string getPsalmAntiphon(const SpecialAntiphonDays inDay) const;

    std::string getNuncDimittisAntiphon(const SpecialAntiphonDays inDay) const;

    HymnSeasons getSeason(const SpecialAntiphonDays inDay) const;

  };

  static inline SpecialAntiphonInitializer s_SAInit;

};


To dispose of the odd man out first: the SpecialAntiphon logic is specific to the Sarum Rite and involves variation that doesn't match anything else.  So Compline owns the enum defining it, the constructor using that enum forces the use to Sarum, and the values are set by the static initializer:

Compline::Compline(const SpecialAntiphonDays inDay):

    m_useHandler(CreateUseHandler(false)),

    m_antiphons(s_SAInit.getPsalmAntiphon(inDay)),

    m_chapter(Grades::DOUBLE, s_SAInit.getSeason(inDay), false),

    m_NDAntiphons(s_SAInit.getNuncDimittisAntiphon(inDay)),

    m_penitentialPsalms(Grades::DOUBLE, Days::MONDAY,

                        s_SAInit.getSeason(inDay), OfficeNames::COMPLINE),

    m_season(s_SAInit.getSeason(inDay)), m_specialDay(SpecialDays::NONE)

}


std::string Compline::SpecialAntiphonInitializer::getPsalmAntiphon(

    const Compline::SpecialAntiphonDays inDay) const

{

  switch (inDay)

    {

      using enum Compline::SpecialAntiphonDays;

    case CHRISTMAS_EVE:

      return "Be ye ready, like unto men that wait for their lord : when he shall return from the wedding.";

    case EPIPHANY:

      return "Thou hast appeared, Christ, Light of Light : to Whom the wise men present gifts. Alleluia, Alleluia, Alleluia.";

    case CANDLEMAS:

      return "A Virgin, she conceived the Word ; a Virgin, she abode : a Virgin she brought forth the King of kings.";

    case HOLY_NAME:

      return "Have mercy upon me, Lord : as Thou usest to do unto those that love Thy Name.";

    }

  return "Have mercy upon me, and hearken unto my prayer";

}

std::string Compline::SpecialAntiphonInitializer::getNuncDimittisAntiphon(

    const Compline::SpecialAntiphonDays inDay) const

{

  switch (inDay)

    {

      using enum Compline::SpecialAntiphonDays;

    case CHRISTMAS_EVE:

      return "Let all men watch and pray : for ye know not when the time is : Watch therefore, for ye know not when the Master of the house cometh : at even, or at midnight, or at the cock-crowing, or in the morning : lest coming suddenly He find you sleeping.";

    case EPIPHANY:

      return "Alleluia. All they from Sheba shall come. Alleluia : They shall bring gold and incense. Alleluia, Alleluia.";

    case CANDLEMAS:

      return "We glorify thee, Mother of God : for of thee Christ was born.";

    case HOLY_NAME:

      return "O King, all glorious among Thy Saints, Who art ever to be praised, yet overpassest utterance: Thou, Lord, art in the midst of us, and we are called by Thy holy Name; leave us not, our God : that in the day of judgment it may please thee to place us in the number of thy Saints and chosen ones, King most blessed";

    }

  return "Preserve us, O Lord, while waking, and guarrd us sleeping: that awake we may be with Christ and in peace may take our rest.";

}

HymnSeasons Compline::SpecialAntiphonInitializer::getSeason(

    const Compline::SpecialAntiphonDays inDay) const

{

  switch (inDay)

    {

      using enum Compline::SpecialAntiphonDays;

    case CHRISTMAS_EVE:

      return HymnSeasons::INCARNATION;

    case EPIPHANY:

      return HymnSeasons::INCARNATION;

    case CANDLEMAS:

      return HymnSeasons::NORMAL;

    case HOLY_NAME:

      return HymnSeasons::NORMAL;

    }

  return HymnSeasons::NORMAL;

}

It's a special case. or a set of special cases, on steroids.

The other constructors follow what one might expect, the two inlined ones plus:

Compline::Compline(const IHoursInfo &inInfo,

                   const IComplineInfo &inComplineInfo):

    m_useHandler(CreateUseHandler(inInfo.followRomanUse())),

    m_antiphons(inComplineInfo.generatePsalmAntiphons()),

    m_chapter(inComplineInfo.generateComplineChapter()),

    m_NDAntiphons(inComplineInfo.generateNuncDimittisAntiphons()),

    m_penitentialPsalms(inInfo.grade(),

                        ((inInfo.grade() == Grades::DOMINICA)

                         || (inInfo.grade() == Grades::DOMINICA_SECOND_CLASS)

                         || (inInfo.grade() == Grades::DOMINICA_FIRST_CLASS))

                            ? Days::SUNDAY

                            : Days::MONDAY,

                        inInfo.getSeason(), OfficeNames::COMPLINE),

    m_season(inInfo.getSeason()), m_specialDay(SpecialDays::NONE)

{

}

The two use handlers capture the variation between the uses:

void Compline::SarumUseHandler::formatEasterInvocation(

    const IEncapsulatedOfficeFormatter &inFormatter) const

{

  inFormatter.formatInvocation(false, false);

}

void Compline::SarumUseHandler::formatIntroductoryChapter(

    const IEncapsulatedOfficeFormatter &inFormatter) const

}

void Compline::SarumUseHandler::formatMedialConfiteor(

    const IEncapsulatedOfficeFormatter &inFormatter) const

{

  inFormatter.formatConfiteor();

  inFormatter.formatResponsory(

      "Wilt Thou not turn again and quicken us, O Lord? ",

      "That Thy people may rejoice in Thee. ");

  inFormatter.formatResponsory("Shew us Thy mercy, O Lord.",

                               "And grant us Thy salvation. ");

}

void Compline::SarumUseHandler::formatPenitentialPsalm(

    const FerialPetitions &inPenitentialPsalm, const IPsalter &inPsalter,

    const IEncapsulatedOfficeFormatter &inFormatter) const

{

  inPenitentialPsalm.formatPenitentialPsalm(inFormatter, inPsalter);

}

void Compline::SarumUseHandler::formatCollect(

    const IEncapsulatedOfficeFormatter &inFormatter) const

{

  inFormatter.formatCollect(

      "Lighten our darkness, we beseech Thee, O Lord, and by Thy great mercy defend us from all perils and dangers of this night, for the love of Thy only Son, our Saviour Jesus Christ: who liveth. Amen.");

}

void Compline::RomanUseHandler::formatEasterInvocation(

    const IEncapsulatedOfficeFormatter &inFormatter) const

{

  inFormatter.formatInvocation(true, false);

}

void Compline::RomanUseHandler::formatIntroductoryChapter(

    const IEncapsulatedOfficeFormatter &inFormatter) const

{

  inFormatter.formatResponsory(

      "Bid, Sir, a blessing.",

      "May the Lord almighty grant us a quiet night and a perfect end.  Amen");

  inFormatter.formatChapter(

      "Brethren, be sober, be vigilant, for your adversary, the devil, as a roaring lion, walketh about, seeking whom he may devour; whom resist steadfast in the faith.  But thou, O Lord, have mercy upon us.",

      "I Pet. i");

  inFormatter.formatResponsory("Our help is in the name of the Lord.",

                               "Who hath made heaven and earth.");

  inFormatter.formatConfiteor();

}


void Compline::RomanUseHandler::formatMedialConfiteor(

    const IEncapsulatedOfficeFormatter &inFormatter) const

}

void Compline::RomanUseHandler::formatPenitentialPsalm(

    const FerialPetitions &inPenitentialPsalm, const IPsalter &inPsalter,

    const IEncapsulatedOfficeFormatter &inFormatter) const

}

void Compline::RomanUseHandler::formatCollect(

    const IEncapsulatedOfficeFormatter &inFormatter) const

{

  inFormatter.formatCollect(

      "Visit, we beseech Thee, O Lord, this dwelling, and drive far from it all snares of the enemy; let Thy holy Angels dwell herein, to preserve us in peace; and let Thy blessing be upon us forever. Through Christ our Lord. Amen.");

}

This all allows the formatting function to be somewhat lengthy but not overly complex:

void Compline::formatOffice(const IEncapsulatedOfficeFormatter &inFormatter,

                            const IPsalter &inPsalter, const bool inIsPriest,

                            const IHymnSource &inHymns)

{

  inFormatter.formatHeading("COMPLINE");

  if ((m_specialDay == SpecialDays::MAUNDY_THURSDAY)

      || (m_specialDay == SpecialDays::GOOD_FRIDAY))

    {

      m_NDAntiphons.formatAntiphon(inFormatter, 1);

      inFormatter.formatGreeting(inIsPriest);

      inFormatter.formatCollect(

          "Almighty God, we beseech thee graciously to behold this thy family, for which our Lord Jesus Christ was contented to be betrayed, and given up into the hands of wicked men, and to suffer death upon the Cross.");

    }

  else if ((m_specialDay == SpecialDays::HOLY_SATURDAY)

           || (m_specialDay == SpecialDays::EASTER_WEEK))

    {

      m_useHandler->formatEasterInvocation(inFormatter);

      m_NDAntiphons.formatAntiphon(inFormatter, 1);

    }

  else

    {

      m_useHandler->formatIntroductoryChapter(inFormatter);

      inFormatter.formatResponsory("Turn us, O God, our Saviour.",

                                   "And let thine anger cease from us.");

      inFormatter.formatGloriaPatri();

      m_psalms.outputPsalms(inFormatter, m_antiphons, inPsalter);

      m_chapter.formatChapter(inFormatter, inHymns, m_season);

      m_NDAntiphons.formatAntiphon(inFormatter, 1);

      inFormatter.formatKyrie();

      inFormatter.formatPaterNoster();

      inFormatter.formatResponsory("I will lay me down in peace.",

                                   "And take my rest.");

      inFormatter.formatCreed();

      inFormatter.formatResponsory(

          "Let us bless the Father, the Son, and the Holy Ghost.",

          "Let us praise him, and magnify him for ever.");

      inFormatter.formatResponsory(

          "Blessed art Thou, O Lord, in the firmament of heaven.",

          "And above all to be praised and magnified for ever.");

      inFormatter.formatResponsory(

          "The Almighty and merciful Lord guard us and give us his blessing.",

          "Amen.");

      m_useHandler->formatMedialConfiteor(inFormatter);

      inFormatter.formatResponsory("Vouchsafe, O Lord.",

                                   "To keep us this day without sin.");

      inFormatter.formatResponsory("O Lord, have mercy upon us.",

                                   "Have mercy upon us.");

      inFormatter.formatResponsory("O Lord, let Thy mercy lighten upon us.",

                                   "As our trust is in Thee,");

      m_useHandler->formatPenitentialPsalm(m_penitentialPsalms, inPsalter,

                                           inFormatter);

      inFormatter.formatResponsory("O Lord, hear my prayer.",

                                   "And let my cry come unto thee.");

      if (inIsPriest)

        inFormatter.formatResponsory("The Lord be with you.",

                                     "And with thy spirit.");


      m_useHandler->formatCollect(inFormatter);

      inFormatter.formatGreeting(inIsPriest);

      inFormatter.formatResponsory("Let us bless the Lord",

                                   "Thanks be to God.");

      inFormatter.formatResponsory(

          "May Almighty God, Father, Son and holy Spirit, bless us and keep us",

          "Amen");

    }

}

Comments

Popular posts from this blog

Boundaries

State Machines

Considerations on an Optimization