Prime Element, and a Minor Refactoring
The Prime Element is simpler than the general Minor Hours elements, because the only thing that can vary at the XML level is the one antiphon. So it inherits directly from the previously-encountered SingleAntiphonElement.
class PrimeElement : public SingleAntiphonElement
{
public:
explicit PrimeElement(std::string_view inText);
~PrimeElement() override;
};
As for the constructor implementation...
Originally, the MinorHoursElement had the following function defined:
void MinorHoursElement::handleEnd(std::string_view inText)
{
if (inText.starts_with(getEndTag()))
{
if (m_chapter.empty() && m_responses.empty() && m_antiphon.empty())
throw OfficeParseException("Cannot have an empty " + m_tag.getName()
+ " element");
incrementLength(getEndTag().length());
}
else
throw OfficeParseException(
"Unexpected element in " + m_tag.getName() + " element", inText);
}
The same logic appears in PrimeElement, except that the test for whether the element is empty is different. Time for a simple refactoring.
1) Encapsulate the test as a function:
bool MinorHoursElement::isEmptyElement() const
{
return (m_chapter.empty() && m_responses.empty() && m_antiphon.empty());
}
2) Modify the old function to call the new one:
void MinorHoursElement::handleEnd(std::string_view inText)
{
if (inText.starts_with(getEndTag()))
{
if (isEmptyElement())
throw OfficeParseException("Cannot have an empty " + m_tag.getName()
+ " element");
incrementLength(getEndTag().length());
}
else
throw OfficeParseException(
"Unexpected element in " + m_tag.getName() + " element", inText);
}
3) Hoist the function to SingleAntiphonElement, making isEmptyElement() pure virtual:
class SingleAntiphonElement : public MultiElementElement
{
...
void handleEnd(std::string_view inText);
virtual bool isEmptyElement() const
};
4) Update PrimeElement, which I will now display in its updated form:
class PrimeElement : public SingleAntiphonElement
{
public:
explicit PrimeElement(std::string_view inText);
~PrimeElement() override;
private:
bool isEmptyElement() const override { return m_antiphon.empty(); }
};
With the constructor:
PrimeElement::PrimeElement(std::string_view inText):
SingleAntiphonElement(inText, "Prime")
{
initialize(inText);
std::string_view rest(inText.substr(getLength()));
adjustBetweenTags(rest);
AntiphonElement element(rest);
m_antiphon = element.getText();
rest.remove_prefix(incrementLength(element.getLength()));
adjustBetweenTags(rest);
handleEnd(rest);
}
Comments
Post a Comment