24#include <unordered_map>
44 using runtime_error::runtime_error;
61 explicit IdMapping(std::shared_ptr<json> documentRoot,
const std::optional<ErrorHandler>& errorHandler = std::nullopt)
62 : m_root(documentRoot), m_errorHandler(errorHandler) {}
73 template <
typename T,
typename IdType>
74 T
get(
const IdType&
id,
const std::optional<Base>& errorLocation = std::nullopt)
const
76 const auto& map = getMap<T>();
77 auto it = map.find(
id);
78 if (it == map.end()) {
79 mapping_error err(
"ID " + formatKeyString(
id) +
" not found in ID mapping");
80 if (m_errorHandler) m_errorHandler.value()(err.what(), errorLocation.value_or(
Document(m_root)));
83 return T(m_root, it->second);
87 template <
typename T,
typename IdType>
90 const auto& map = getMap<T>();
91 return map.find(
id) != map.end();
100 template <
typename T,
typename IdType>
101 void add(
const IdType&
id,
const T& value)
103 auto result = getMap<T>().emplace(
id, value.pointer());
104 if (!result.second) {
105 mapping_error err(
"ID " + formatKeyString(
id) +
" already exists at " + result.first->second.to_string());
106 if (m_errorHandler) {
107 m_errorHandler.value()(err.what(), value);
121 const auto part = get<mnx::Part>(partId);
122 const auto measures = part.measures();
123 if (!measures || measureIndex >= measures.value().size()) {
124 mapping_error err(
"Part \'" + partId +
"\" lacks a corresponding measure for the input global measure.");
125 if (m_errorHandler) m_errorHandler.value()(err.what(), globalMeasure);
128 return measures.value()[measureIndex];
132 std::shared_ptr<json> m_root;
133 std::optional<ErrorHandler> m_errorHandler;
135 using Map = std::unordered_map<std::string, json_pointer>;
141 std::unordered_map<int, json_pointer> m_globalMeasures;
145 static constexpr bool always_false =
false;
147 template <
typename T,
typename Self>
148 static auto& getMapImpl(Self& self) {
149 if constexpr (std::is_same_v<T, mnx::Part>) {
150 return self.m_partMap;
151 }
else if constexpr (std::is_same_v<T, mnx::Layout>) {
152 return self.m_layoutMap;
153 }
else if constexpr (std::is_same_v<T, mnx::sequence::Note>) {
154 return self.m_noteMap;
155 }
else if constexpr (std::is_same_v<T, mnx::sequence::Event>) {
156 return self.m_eventMap;
157 }
else if constexpr (std::is_same_v<T, mnx::global::Measure>) {
158 return self.m_globalMeasures;
160 static_assert(always_false<T>,
"Unsupported type for IdMapping::getMap");
164 template <
typename T>
165 const auto& getMap()
const
166 {
return getMapImpl<T>(*
this); }
168 template <
typename T>
170 {
return getMapImpl<T>(*
this); }
172 template <
typename KeyType>
173 static std::string formatKeyString(
const KeyType& key) {
174 if constexpr (std::is_same_v<KeyType, std::string>) {
175 return "\"" + key +
"\"";
177 std::ostringstream oss;
size_t calcArrayIndex() const
Calculates the array index of the current instance within the array.
Definition BaseTypes.h:620
Represents an MNX document and provides methods for loading and saving.
Definition Document.h:87
Represents a single global measure instance within an MNX document.
Definition Global.h:235
Represents a single measuer in a part in an MNX document. It contains the majority of the musical inf...
Definition Part.h:203
Provides type-safe ID-based lookup for elements in an MNX document.
Definition IdMapping.h:54
void add(const IdType &id, const T &value)
Adds a key to the mapping. If there is no error handler, it throws mapping_error if there is a duplic...
Definition IdMapping.h:101
mnx::part::Measure getPartMeasure(const mnx::global::Measure &globalMeasure, const std::string &partId) const
Returns the part::Measure instance associated with the input global::Measure.
Definition IdMapping.h:118
IdMapping(std::shared_ptr< json > documentRoot, const std::optional< ErrorHandler > &errorHandler=std::nullopt)
Constructs the index for a given document.
Definition IdMapping.h:61
T get(const IdType &id, const std::optional< Base > &errorLocation=std::nullopt) const
Looks up an object by string ID.
Definition IdMapping.h:74
bool exists(const IdType &id) const
Returns whether the specified ID exists in the mapping.
Definition IdMapping.h:88
base class for mapping error exceptions
Definition IdMapping.h:43