MUSX Document Model
Loading...
Searching...
No Matches
BaseClasses.h
1/*
2 * Copyright (C) 2025, Robert Patterson
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22#pragma once
23
24#include <cassert>
25#include <filesystem>
26#include <set>
27
28#include "musx/dom/Fundamentals.h"
29#include "musx/xml/XmlInterface.h"
30#include "musx/util/Logger.h"
31
32namespace musx {
33
38namespace dom {
39
40namespace others {
41class PartDefinition;
42}
43
47class integrity_error : public std::runtime_error
48{
49public:
50 using std::runtime_error::runtime_error;
51};
52
53class Document;
55using DocumentPtr = std::shared_ptr<Document>;
57using DocumentWeakPtr = std::weak_ptr<Document>;
58
63class Base
64{
65public:
67 using SharedNodes = std::set<std::string>;
68
71 enum class ShareMode
72 {
73 // this enum was giving Doxygen fits until I switched to using the slash-splat-bang-lt comment commands.
74 All,
75 Partial,
76 None
77 };
78
82 virtual ~Base() noexcept(false) = default;
83
90 {
91 auto document = m_document.lock();
92 assert(document); // program bug if this pointer goes out of scope.
93 if (!document) {
94 throw std::logic_error("Document pointer is no longer valid.");
95 }
96 return document;
97 }
98
102 Cmper getPartId() const { return m_partId; }
103
105 std::shared_ptr<others::PartDefinition> getPartDefinition() const;
106
110 ShareMode getShareMode() const { return m_shareMode; }
111
115 const SharedNodes& getUnlinkedNodes() const { return m_unlinkedNodes; }
116
120 void addUnlinkedNode(const std::string& nodeName)
121 {
122 m_unlinkedNodes.insert(nodeName);
123 }
124
133 virtual void integrityCheck() { }
134
145 virtual bool requireAllFields() const { return true; }
146
147protected:
155 Base(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode)
156 : m_document(document), m_partId(partId), m_shareMode(shareMode) {}
157
159 Base& operator=(const Base&) { return *this; }
160
161private:
162 const DocumentWeakPtr m_document;
163 const Cmper m_partId;
164 const ShareMode m_shareMode;
165 SharedNodes m_unlinkedNodes;
166};
167
173class CommonClassBase : public Base
174{
175public:
182 : Base(document, SCORE_PARTID, ShareMode::All) {}
183
184protected:
185 // Because the part ID and share mode are hard-coded for this category of classes,
186 // these Base functions do not return useful results. However, we allow our subclasses
187 // to use their own versions of these functions (esp. `getPartId`) to avoid promiscuous
188 // hard-coding of SCORE_PARTID. The rules may change in the future.
190 using Base::getPartId;
191 using Base::getShareMode;
193};
194
200class OptionsBase : public Base {
201protected:
209 OptionsBase(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode)
210 : Base(document, partId, shareMode) {}
211};
212
219class OthersBase : public Base
220{
221protected:
231 OthersBase(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode, Cmper cmper, std::optional<Inci> inci = std::nullopt)
232 : Base(document, partId, shareMode), m_cmper(cmper), m_inci(inci) {}
233
234public:
240 Cmper getCmper() const { return m_cmper; }
241
247 std::optional<Inci> getInci() const { return m_inci; }
248
249private:
250 Cmper m_cmper;
251 std::optional<Inci> m_inci;
252};
253
257template <typename ElementType, size_t REQUIRED_SIZE = 0>
259{
260private:
261 virtual std::string_view xmlTag() const = 0;
262
263public:
265 explicit OthersArray(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode, Cmper cmper)
266 : OthersBase(document, partId, shareMode, cmper)
267 {
268 }
269
270 std::vector<ElementType> values;
272
274 void integrityCheck() override
275 {
277 if constexpr (REQUIRED_SIZE) {
278 const size_t originalSize = values.size();
279 values.resize(REQUIRED_SIZE); // resize first, in case MUSX_INTEGRITY_ERROR throws. (Avoid unreachable code warning.)
280 if (originalSize < REQUIRED_SIZE) {
281 MUSX_INTEGRITY_ERROR("Array with xml tag " + std::string(xmlTag()) + " and cmper " + std::to_string(getCmper())
282 + " has fewer than " + std::to_string(REQUIRED_SIZE) + " elements.");
283 }
284 }
285 }
286};
287
294class DetailsBase : public Base
295{
296protected:
307 DetailsBase(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode, Cmper cmper1, Cmper cmper2, std::optional<Inci> inci = std::nullopt)
308 : Base(document, partId, shareMode), m_cmper1(cmper1), m_cmper2(cmper2), m_inci(inci) {}
309
310public:
314 Cmper getCmper1() const { return m_cmper1; }
315
319 Cmper getCmper2() const { return m_cmper2; }
320
324 std::optional<Inci> getInci() const { return m_inci; }
325
326private:
327 Cmper m_cmper1;
328 Cmper m_cmper2;
329 std::optional<Inci> m_inci;
330};
331
336{
337protected:
347 EntryDetailsBase(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode, EntryNumber entnum, std::optional<Inci> inci = std::nullopt)
348 : DetailsBase(document, partId, shareMode, Cmper(entnum >> 16), Cmper(entnum & 0xffff), inci) {}
349
350public:
354 EntryNumber getEntryNumber() const { return EntryNumber(getCmper1()) << 16 | EntryNumber(getCmper2()); }
355
356private:
359};
360
361class NoteInfoPtr;
362
365{
366public:
368 virtual NoteNumber getNoteId() const = 0;
369
370protected:
372};
373
374class FontInfo;
380class TextsBase : public Base
381{
382public:
391 TextsBase(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode, Cmper textNumber)
392 : Base(document, partId, shareMode), m_textNumber(textNumber) {}
393
394 std::string text;
395
399 Cmper getTextNumber() const { return m_textNumber; }
400
404 void setTextNumber(Cmper textNumber) { m_textNumber = textNumber; }
405
410 std::shared_ptr<FontInfo> parseFirstFontInfo() const;
411
412private:
413 Cmper m_textNumber;
414};
415
416} // namespace dom
417} // namespace musx
Base class to enforce polymorphism across all DOM classes.
Definition BaseClasses.h:64
Cmper getPartId() const
Gets the partId for this instance (or 0 for score)
Definition BaseClasses.h:102
DocumentPtr getDocument() const
Gets a reference to the Document.
Definition BaseClasses.h:89
virtual void integrityCheck()
Allows a class to determine if it has been properly contructed by the factory and fix issues that it ...
Definition BaseClasses.h:133
virtual bool requireAllFields() const
Specifies if the parser should alert (print or throw) when an unknown xml tag is found for this class...
Definition BaseClasses.h:145
Base & operator=(const Base &)
assignment constructor: m_unlinkedNodes is intentionally omitted
Definition BaseClasses.h:159
Base(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode)
Constructs the base class and enforces the static constexpr XmlNodeName.
Definition BaseClasses.h:155
ShareMode getShareMode() const
Gets the sharing mode for this instance.
Definition BaseClasses.h:110
std::set< std::string > SharedNodes
The container type for shared nodes.
Definition BaseClasses.h:67
const SharedNodes & getUnlinkedNodes() const
Gets the unlinked nodes for this instance. (Only populated for ShareMode::Partial)
Definition BaseClasses.h:115
void addUnlinkedNode(const std::string &nodeName)
Adds a shared node for this instance.
Definition BaseClasses.h:120
std::shared_ptr< others::PartDefinition > getPartDefinition() const
Gets the others::PartDefinition corresponding to getPartId.
Definition Implementations.cpp:49
ShareMode
Describes how this instance is shared between part and score.
Definition BaseClasses.h:72
virtual ~Base() noexcept(false)=default
Virtual destructor for polymorphic behavior.
Base class for classes that are commonly used among others, details, entries, and/or texts....
Definition BaseClasses.h:174
CommonClassBase(const DocumentWeakPtr &document)
Constructs a CommonClassBase object.
Definition BaseClasses.h:181
Base class for all "details" types.
Definition BaseClasses.h:295
DetailsBase(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode, Cmper cmper1, Cmper cmper2, std::optional< Inci > inci=std::nullopt)
Constructs a DetailsBase object.
Definition BaseClasses.h:307
Cmper getCmper1() const
Gets the cmper1 key value.
Definition BaseClasses.h:314
Cmper getCmper2() const
Gets the cmper2 key value.
Definition BaseClasses.h:319
std::optional< Inci > getInci() const
Gets the optional array index (inci).
Definition BaseClasses.h:324
Represents a document object that encapsulates the entire EnigmaXML structure.
Definition Document.h:51
Base class for all "details" types that use entnum rather than cmper and cmper.
Definition BaseClasses.h:336
EntryDetailsBase(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode, EntryNumber entnum, std::optional< Inci > inci=std::nullopt)
Constructs a EntryDetailsBase object.
Definition BaseClasses.h:347
EntryNumber getEntryNumber() const
Gets the entnum key value.
Definition BaseClasses.h:354
Represents the default font settings for a particular element type.
Definition CommonClasses.h:83
Base class note details. Note details are entry details associated with a note ID.
Definition BaseClasses.h:365
virtual NoteNumber getNoteId() const =0
Required virtual function that returns the note id.
Base class for all "options" types.
Definition BaseClasses.h:200
OptionsBase(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode)
Constructs the OptionsBase and validates XmlNodeName in the derived class.
Definition BaseClasses.h:209
Template pattern for OthersBase items consisting of an array of a single item.
Definition BaseClasses.h:259
std::vector< ElementType > values
Definition BaseClasses.h:270
OthersArray(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode, Cmper cmper)
Constructor function.
Definition BaseClasses.h:265
void integrityCheck() override
Override of Base::integrityCheck.
Definition BaseClasses.h:274
Base class for all "others" types.
Definition BaseClasses.h:220
std::optional< Inci > getInci() const
Gets the optional array index (inci).
Definition BaseClasses.h:247
OthersBase(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode, Cmper cmper, std::optional< Inci > inci=std::nullopt)
Constructs an OthersBase object.
Definition BaseClasses.h:231
Cmper getCmper() const
Gets the cmper key value.
Definition BaseClasses.h:240
Base class for all text blocks.
Definition BaseClasses.h:381
Cmper getTextNumber() const
Returns the raw text number.
Definition BaseClasses.h:399
std::string text
Raw Enigma string (with Enigma string tags), encoded UTF-8.
Definition BaseClasses.h:394
std::shared_ptr< FontInfo > parseFirstFontInfo() const
Returns a shared pointer to a FontInfo instance that reflects the first font information in the text.
Definition Implementations.cpp:2385
TextsBase(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode, Cmper textNumber)
Constructs a TextsBase object.
Definition BaseClasses.h:391
void setTextNumber(Cmper textNumber)
Sets the raw text number.
Definition BaseClasses.h:404
Exception for integrity errors. (Used when MUSX_THROW_ON_INTEGRITY_CHECK_FAIL is defined....
Definition BaseClasses.h:48
Represents the attributes of a Finale "partDef".
Definition Others.h:1346
constexpr Cmper SCORE_PARTID
The part id of the score.
Definition Fundamentals.h:75
uint16_t Cmper
Enigma "comperator" key type.
Definition Fundamentals.h:55
std::weak_ptr< Document > DocumentWeakPtr
Shared weak Document pointer.
Definition BaseClasses.h:57
int32_t EntryNumber
Entry identifier.
Definition Fundamentals.h:68
uint16_t NoteNumber
Note identifier.
Definition Fundamentals.h:69
std::shared_ptr< Document > DocumentPtr
Shared Document pointer.
Definition BaseClasses.h:55
object model for musx file (enigmaxml)
Definition BaseClasses.h:32