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