Line data Source code
1 : // DUNE DAQ modification notice:
2 : // This file has been modified from the original ATLAS oks source for the DUNE DAQ project.
3 : // Fork baseline commit: oks-08-03-04 (2022-04-14).
4 : // Renamed since fork: no.
5 :
6 : #define _OksBuildDll_
7 :
8 : #include "oks/relationship.hpp"
9 : #include "oks/class.hpp"
10 : #include "oks/cstring.hpp"
11 : #include "oks/kernel.hpp"
12 : #include "oks/xml.hpp"
13 :
14 : #include <sstream>
15 :
16 : namespace dunedaq {
17 : namespace oks {
18 :
19 : const char OksRelationship::relationship_xml_tag[] = "relationship";
20 : const char OksRelationship::name_xml_attr[] = "name";
21 : const char OksRelationship::description_xml_attr[] = "description";
22 : const char OksRelationship::class_type_xml_attr[] = "class-type";
23 : const char OksRelationship::low_cc_xml_attr[] = "low-cc";
24 : const char OksRelationship::high_cc_xml_attr[] = "high-cc";
25 : const char OksRelationship::is_composite_xml_attr[] = "is-composite";
26 : const char OksRelationship::is_exclusive_xml_attr[] = "is-exclusive";
27 : const char OksRelationship::is_dependent_xml_attr[] = "is-dependent";
28 : const char OksRelationship::ordered_xml_attr[] = "ordered";
29 :
30 : OksRelationship::CardinalityConstraint
31 12800 : OksRelationship::str2card(const char* s) noexcept
32 : {
33 12800 : return (oks::cmp_str3(s, "one") ? One : oks::cmp_str4(s, "zero") ? Zero : Many);
34 : }
35 :
36 : const char*
37 0 : OksRelationship::card2str(CardinalityConstraint cc) noexcept
38 : {
39 0 : return (cc == Zero ? "zero" : cc == One ? "one" : "many");
40 : }
41 :
42 0 : OksRelationship::OksRelationship(const std::string& nm, OksClass* p)
43 0 : : p_name(nm)
44 0 : , p_low_cc(Zero)
45 0 : , p_high_cc(Many)
46 0 : , p_composite(false)
47 0 : , p_exclusive(false)
48 0 : , p_dependent(false)
49 0 : , p_class(p)
50 0 : , p_class_type(nullptr)
51 0 : , p_ordered(false)
52 : {
53 0 : oks::validate_not_empty(p_name, "relationship name");
54 0 : }
55 :
56 0 : OksRelationship::OksRelationship(const std::string& nm,
57 : const std::string& rc,
58 : CardinalityConstraint l_cc,
59 : CardinalityConstraint h_cc,
60 : bool cm,
61 : bool excl,
62 : bool dp,
63 : const std::string& desc,
64 0 : OksClass* p)
65 0 : : p_name(nm)
66 0 : , p_rclass(rc)
67 0 : , p_low_cc(l_cc)
68 0 : , p_high_cc(h_cc)
69 0 : , p_composite(cm)
70 0 : , p_exclusive(excl)
71 0 : , p_dependent(dp)
72 0 : , p_description(desc)
73 0 : , p_class(p)
74 0 : , p_class_type(nullptr)
75 0 : , p_ordered(false)
76 : {
77 0 : oks::validate_not_empty(p_name, "relationship name");
78 0 : oks::validate_not_empty(p_rclass, "relationship class");
79 0 : }
80 :
81 : bool
82 315 : OksRelationship::operator==(const class OksRelationship& r) const
83 : {
84 315 : return ((this == &r) ||
85 0 : ((p_name == r.p_name) && (p_rclass == r.p_rclass) && (p_low_cc == r.p_low_cc) && (p_high_cc == r.p_high_cc) &&
86 0 : (p_composite == r.p_composite) && (p_exclusive == r.p_exclusive) && (p_dependent == r.p_dependent) &&
87 0 : (p_description == r.p_description) && (p_ordered == r.p_ordered)));
88 : }
89 :
90 : std::ostream&
91 0 : operator<<(std::ostream& s, const OksRelationship& r)
92 : {
93 0 : s << "Relationship name: \"" << r.p_name
94 : << "\"\n"
95 : " class type: \""
96 0 : << r.p_rclass
97 : << "\"\n"
98 : " low cardinality constraint is "
99 0 : << OksRelationship::card2str(r.p_low_cc)
100 : << "\n"
101 : " high cardinality constraint is "
102 0 : << OksRelationship::card2str(r.p_high_cc)
103 : << "\n"
104 : " is"
105 0 : << (r.p_composite == true ? "" : " not")
106 : << " composite reference\n"
107 : " is"
108 0 : << (r.p_exclusive == true ? "" : " not")
109 : << " exclusive reference\n"
110 : " is "
111 0 : << (r.p_dependent == true ? "dependent" : "shared")
112 : << " reference\n"
113 : " has description: \""
114 0 : << r.p_description
115 : << "\"\n"
116 : " is "
117 0 : << (r.p_ordered == true ? "ordered" : "unordered") << std::endl;
118 :
119 0 : return s;
120 : }
121 :
122 : void
123 0 : OksRelationship::save(OksXmlOutputStream& s) const
124 : {
125 0 : s.put(" ");
126 :
127 0 : s.put_start_tag(relationship_xml_tag, sizeof(relationship_xml_tag) - 1);
128 :
129 0 : s.put_attribute(name_xml_attr, sizeof(name_xml_attr) - 1, p_name.c_str());
130 :
131 0 : if (!p_description.empty())
132 0 : s.put_attribute(description_xml_attr, sizeof(description_xml_attr) - 1, p_description.c_str());
133 :
134 0 : s.put_attribute(class_type_xml_attr, sizeof(class_type_xml_attr) - 1, p_rclass.c_str());
135 0 : s.put_attribute(low_cc_xml_attr, sizeof(low_cc_xml_attr) - 1, card2str(p_low_cc));
136 0 : s.put_attribute(high_cc_xml_attr, sizeof(high_cc_xml_attr) - 1, card2str(p_high_cc));
137 0 : s.put_attribute(is_composite_xml_attr, sizeof(is_composite_xml_attr) - 1, oks::xml::bool2str(p_composite));
138 0 : s.put_attribute(is_exclusive_xml_attr, sizeof(is_exclusive_xml_attr) - 1, oks::xml::bool2str(p_exclusive));
139 0 : s.put_attribute(is_dependent_xml_attr, sizeof(is_dependent_xml_attr) - 1, oks::xml::bool2str(p_dependent));
140 :
141 0 : if (p_ordered)
142 0 : s.put_attribute(ordered_xml_attr, sizeof(ordered_xml_attr) - 1, oks::xml::bool2str(p_ordered));
143 :
144 0 : s.put_end_tag();
145 0 : }
146 :
147 6400 : OksRelationship::OksRelationship(OksXmlInputStream& s, OksClass* parent)
148 6400 : : p_low_cc(Zero)
149 6400 : , p_high_cc(Many)
150 6400 : , p_composite(false)
151 6400 : , p_exclusive(false)
152 6400 : , p_dependent(false)
153 6400 : , p_class(parent)
154 6400 : , p_class_type(nullptr)
155 6400 : , p_ordered(false)
156 : {
157 53970 : try {
158 101540 : while (true) {
159 53970 : OksXmlAttribute attr(s);
160 :
161 : // check for close of tag
162 :
163 53970 : if (oks::cmp_str1(attr.name(), "/")) {
164 : break;
165 : }
166 :
167 : // check for known oks-relationship' attributes
168 :
169 47570 : else if (oks::cmp_str4(attr.name(), name_xml_attr))
170 6400 : p_name.assign(attr.value(), attr.value_len());
171 41170 : else if (oks::cmp_str11(attr.name(), description_xml_attr))
172 2761 : p_description.assign(attr.value(), attr.value_len());
173 38409 : else if (oks::cmp_str10(attr.name(), class_type_xml_attr))
174 6400 : p_rclass.assign(attr.value(), attr.value_len());
175 32009 : else if (oks::cmp_str6(attr.name(), low_cc_xml_attr))
176 6400 : p_low_cc = str2card(attr.value());
177 25609 : else if (oks::cmp_str7(attr.name(), high_cc_xml_attr))
178 6400 : p_high_cc = str2card(attr.value());
179 19209 : else if (oks::cmp_str12(attr.name(), is_composite_xml_attr))
180 6400 : p_composite = oks::xml::str2bool(attr.value());
181 12809 : else if (oks::cmp_str12(attr.name(), is_exclusive_xml_attr))
182 6400 : p_exclusive = oks::xml::str2bool(attr.value());
183 6409 : else if (oks::cmp_str12(attr.name(), is_dependent_xml_attr))
184 6400 : p_dependent = oks::xml::str2bool(attr.value());
185 9 : else if (oks::cmp_str7(attr.name(), ordered_xml_attr))
186 9 : p_ordered = oks::xml::str2bool(attr.value());
187 0 : else if (!strcmp(attr.name(), "multi-value-implementation")) {
188 0 : s.error_msg("OksRelationship::OksRelationship(OksXmlInputStream&)")
189 0 : << "Obsolete oks-relationship\'s attribute \'" << attr.name() << "\'\n";
190 : } else {
191 0 : s.throw_unexpected_attribute(attr.name());
192 : }
193 47570 : }
194 0 : } catch (oks::exception& e) {
195 0 : throw oks::FailedRead("xml attribute", e);
196 0 : } catch (std::exception& e) {
197 0 : throw oks::FailedRead("xml attribute", e.what());
198 0 : }
199 :
200 : // check validity of read values
201 :
202 6400 : try {
203 6400 : oks::validate_not_empty(p_name, "relationship name");
204 6400 : oks::validate_not_empty(p_rclass, "relationship class");
205 0 : } catch (std::exception& ex) {
206 0 : throw oks::FailedRead("oks relationship", oks::BadFileData(ex.what(), s.get_line_no(), s.get_line_pos()));
207 0 : }
208 6400 : }
209 :
210 : void
211 0 : OksRelationship::set_name(const std::string& new_name)
212 : {
213 : // ignore when name is the same
214 :
215 0 : if (p_name == new_name)
216 : return;
217 :
218 : // additional checks are required,
219 : // if the relationship already belongs to some class
220 :
221 0 : if (p_class) {
222 :
223 : // check maximum allowed length for relationship name
224 :
225 0 : try {
226 0 : oks::validate_not_empty(new_name, "name");
227 0 : } catch (std::exception& ex) {
228 0 : throw oks::SetOperationFailed("OksRelationship::set_name", ex.what());
229 0 : }
230 :
231 : // having a direct relationship with the same name is an error
232 :
233 0 : if (p_class->find_direct_relationship(new_name) != 0) {
234 0 : std::ostringstream text;
235 0 : text << "Class \"" << p_class->get_name() << "\" already has direct relationship \"" << new_name << '\"';
236 0 : throw oks::SetOperationFailed("OksRelationship::set_name", text.str());
237 0 : }
238 :
239 : // check possibility to lock the file
240 :
241 0 : p_class->lock_file("OksRelationship::set_name");
242 :
243 : // probably a non-direct relationship already exists
244 :
245 0 : OksRelationship* r = p_class->find_relationship(new_name);
246 :
247 : // change the name
248 :
249 0 : p_name = new_name;
250 :
251 : // registrate the change
252 :
253 0 : p_class->registrate_class_change(OksClass::ChangeRelationshipsList, (const void*)r);
254 : } else {
255 0 : p_name = new_name;
256 : }
257 : }
258 :
259 : void
260 0 : OksRelationship::set_type(const std::string& cn)
261 : {
262 0 : if (p_rclass == cn)
263 : return;
264 :
265 0 : if (!p_class || !p_class->p_kernel || (p_class_type = p_class->p_kernel->find_class(cn)) != 0) {
266 0 : if (p_class)
267 0 : p_class->lock_file("OksRelationship::set_type");
268 :
269 0 : p_rclass = cn;
270 :
271 0 : if (p_class) {
272 0 : p_class->registrate_class_change(OksClass::ChangeRelationshipClassType, (const void*)this);
273 0 : p_class->registrate_relationship_change(this);
274 : }
275 : } else {
276 0 : std::ostringstream text;
277 0 : text << "cannot find class \"" << cn << '\"';
278 0 : throw oks::SetOperationFailed("OksRelationship::set_type", text.str());
279 0 : }
280 : }
281 :
282 : void
283 0 : OksRelationship::set_description(const std::string& desc)
284 : {
285 0 : if (p_description != desc) {
286 0 : if (p_class)
287 0 : p_class->lock_file("OksRelationship::set_description");
288 :
289 0 : p_description = desc;
290 :
291 0 : if (p_class)
292 0 : p_class->registrate_class_change(OksClass::ChangeRelationshipDescription, (const void*)this);
293 : }
294 0 : }
295 :
296 : void
297 0 : OksRelationship::set_low_cardinality_constraint(CardinalityConstraint l_cc)
298 : {
299 0 : if (p_low_cc != l_cc) {
300 0 : if (p_class)
301 0 : p_class->lock_file("OksRelationship::set_low_cardinality_constraint");
302 :
303 0 : CardinalityConstraint old_cc = p_low_cc;
304 :
305 0 : p_low_cc = l_cc;
306 :
307 0 : if (p_class) {
308 0 : p_class->registrate_class_change(OksClass::ChangeRelationshipLowCC, (const void*)this);
309 :
310 0 : if (p_low_cc == Many || old_cc == Many)
311 0 : p_class->registrate_relationship_change(this);
312 : }
313 : }
314 0 : }
315 :
316 : void
317 0 : OksRelationship::set_high_cardinality_constraint(CardinalityConstraint h_cc)
318 : {
319 0 : if (p_high_cc != h_cc) {
320 0 : if (p_class)
321 0 : p_class->lock_file("OksRelationship::set_high_cardinality_constraint");
322 :
323 0 : CardinalityConstraint old_cc = p_high_cc;
324 :
325 0 : p_high_cc = h_cc;
326 :
327 0 : if (p_class) {
328 0 : p_class->registrate_class_change(OksClass::ChangeRelationshipHighCC, (const void*)this);
329 :
330 0 : if (p_high_cc == Many || old_cc == Many)
331 0 : p_class->registrate_relationship_change(this);
332 : }
333 : }
334 0 : }
335 :
336 : void
337 0 : OksRelationship::set_is_composite(bool cm)
338 : {
339 0 : if (p_composite != cm) {
340 0 : if (p_class)
341 0 : p_class->lock_file("OksRelationship::set_is_composite");
342 :
343 0 : p_composite = cm;
344 :
345 0 : if (p_class)
346 0 : p_class->registrate_class_change(OksClass::ChangeRelationshipComposite, (const void*)this);
347 : }
348 0 : }
349 :
350 : void
351 0 : OksRelationship::set_is_exclusive(bool ex)
352 : {
353 0 : if (p_exclusive != ex) {
354 0 : if (p_class)
355 0 : p_class->lock_file("OksRelationship::set_is_exclusive");
356 :
357 0 : p_exclusive = ex;
358 :
359 0 : if (p_class)
360 0 : p_class->registrate_class_change(OksClass::ChangeRelationshipExclusive, (const void*)this);
361 : }
362 0 : }
363 :
364 : void
365 0 : OksRelationship::set_is_dependent(bool dp)
366 : {
367 0 : if (p_dependent != dp) {
368 0 : if (p_class)
369 0 : p_class->lock_file("OksRelationship::set_is_dependent");
370 :
371 0 : p_dependent = dp;
372 :
373 0 : if (p_class)
374 0 : p_class->registrate_class_change(OksClass::ChangeRelationshipDependent, (const void*)this);
375 : }
376 0 : }
377 :
378 : } // namespace oks
379 : } // namespace dunedaq
|