Line data Source code
1 : /**
2 : * \file oks/object.h
3 : *
4 : * This file is part of the OKS package.
5 : * Author: Igor SOLOVIEV "https://phonebook.cern.ch/phonebook/#personDetails/?id=432778"
6 : *
7 : * This file contains the declarations for the OKS object.
8 : */
9 :
10 : #ifndef OKS_OBJECT_H
11 : #define OKS_OBJECT_H
12 :
13 : #include "oks/defs.hpp"
14 : #include "oks/file.hpp"
15 : #include "oks/exceptions.hpp"
16 :
17 : #include <stdint.h>
18 :
19 : #include <string>
20 : #include <list>
21 : #include <set>
22 : #include <map>
23 : #include <functional>
24 :
25 : #include <boost/date_time/gregorian/greg_date.hpp>
26 : #include <boost/date_time/posix_time/ptime.hpp>
27 : #include <boost/pool/pool_alloc.hpp>
28 :
29 : #include <unordered_map>
30 : #include <unordered_set>
31 :
32 :
33 : namespace dunedaq {
34 : namespace oks {
35 :
36 :
37 : /// Forward declarations
38 :
39 : class OksKernel;
40 : class OksFile;
41 : struct OksData;
42 : class OksClass;
43 : class OksObject;
44 : class OksAttribute;
45 : class OksRelationship;
46 : class OksMethod;
47 : class OksQueryExpression;
48 : struct OksAliasTable;
49 : class OksXmlOutputStream;
50 : class OksXmlInputStream;
51 : struct OksXmlToken;
52 : struct OksXmlValue;
53 : struct OksXmlRelValue;
54 :
55 : /// @addtogroup oks
56 :
57 : class QueryPathExpression;
58 : class QueryPath;
59 :
60 :
61 : /** Failed to create an object. **/
62 :
63 : class FailedCreateObject : public exception {
64 :
65 : public:
66 :
67 : /** Get reason from nested oks exception. **/
68 : FailedCreateObject(const OksObject * o, const exception& reason) noexcept : exception (fill(o, reason.what()), reason.level() + 1) { }
69 :
70 : /** Get reason from nested non-oks exception. **/
71 0 : FailedCreateObject(const OksObject * o, const std::string& reason) noexcept : exception (fill(o, reason), 0) { }
72 :
73 0 : virtual ~FailedCreateObject() noexcept { }
74 :
75 :
76 : private:
77 :
78 : static std::string fill(const OksObject * o, const std::string& reason);
79 : };
80 :
81 :
82 : /** Failed to read an object. **/
83 :
84 : class FailedReadObject : public exception {
85 :
86 : public:
87 :
88 : /** Get reason from nested oks exception. **/
89 0 : FailedReadObject(const OksObject * o, const std::string& what, const exception& reason) noexcept : exception (fill(o, what, reason.what()), reason.level() + 1) { }
90 :
91 : /** Get reason from nested non-oks exception. **/
92 0 : FailedReadObject(const OksObject * o, const std::string& what, const std::string& reason) noexcept : exception (fill(o, what, reason), 0) { }
93 :
94 0 : virtual ~FailedReadObject() noexcept { }
95 :
96 :
97 : private:
98 :
99 : static std::string fill(const OksObject * o, const std::string& what, const std::string& reason);
100 : };
101 :
102 :
103 : /** Failed to save an object. **/
104 :
105 : class FailedSaveObject : public exception {
106 :
107 : public:
108 :
109 : /** Get reason from nested oks exception. **/
110 0 : FailedSaveObject(const OksObject * o, const exception& reason) noexcept : exception (fill(o, reason.what()), reason.level() + 1) { }
111 :
112 : /** Get reason from nested non-oks exception. **/
113 0 : FailedSaveObject(const OksObject * o, const std::string& reason) noexcept : exception (fill(o, reason), 0) { }
114 :
115 0 : virtual ~FailedSaveObject() noexcept { }
116 :
117 :
118 : private:
119 :
120 : static std::string fill(const OksObject * o, const std::string& reason);
121 :
122 : };
123 :
124 :
125 : /** Failed to rename an object. **/
126 :
127 : class FailedRenameObject : public exception {
128 :
129 : public:
130 :
131 : /** Get reason from nested oks exception. **/
132 0 : FailedRenameObject(const OksObject * o, const exception& reason) noexcept : exception (fill(o, reason.what()), reason.level() + 1) { }
133 :
134 : /** Get reason from nested non-oks exception. **/
135 0 : FailedRenameObject(const OksObject * o, const std::string& reason) noexcept : exception (fill(o, reason), 0) { }
136 :
137 0 : virtual ~FailedRenameObject() noexcept { }
138 :
139 :
140 : private:
141 :
142 : static std::string fill(const OksObject * o, const std::string& reason);
143 :
144 : };
145 :
146 :
147 : /** Failed to rename an object. **/
148 :
149 : class FailedDestoyObject : public exception {
150 :
151 : public:
152 :
153 : /** Get reason from nested oks exception. **/
154 0 : FailedDestoyObject(const OksObject * o, const exception& reason) noexcept : exception (fill(o, reason.what()), reason.level() + 1) { }
155 :
156 : /** Get reason from nested non-oks exception. **/
157 0 : FailedDestoyObject(const OksObject * o, const std::string& reason) noexcept : exception (fill(o, reason), 0) { }
158 :
159 0 : virtual ~FailedDestoyObject() noexcept { }
160 :
161 :
162 : private:
163 :
164 : static std::string fill(const OksObject * o, const std::string& reason);
165 :
166 : };
167 :
168 :
169 : /** Failed to read a value since it is out of range. **/
170 :
171 : class AttributeRangeError : public exception {
172 :
173 : public:
174 :
175 : /** Get reason from nested non-oks exception. **/
176 0 : AttributeRangeError(const OksData * d, const std::string& range) noexcept : exception (fill(d, range), 0) { }
177 :
178 0 : virtual ~AttributeRangeError() noexcept { }
179 :
180 :
181 : private:
182 :
183 : static std::string fill(const OksData * d, const std::string& range);
184 :
185 : };
186 :
187 :
188 : /** Failed to read a value since it does not match to expected type. **/
189 :
190 : class AttributeReadError : public exception {
191 :
192 : public:
193 :
194 : /** Get reason from nested oks exception. **/
195 0 : AttributeReadError(const char * value, const char * type, const exception& reason) noexcept : exception (fill(value, type, reason.what()), reason.level() + 1) { }
196 :
197 : /** Get reason from nested non-oks exception. **/
198 0 : AttributeReadError(const char * value, const char * type, const std::string& reason) noexcept : exception (fill(value, type, reason), 0) { }
199 :
200 : /** Get reason from nested oks exception. **/
201 : AttributeReadError(const char * type, const exception& reason) noexcept : exception (fill(type, reason.what()), reason.level() + 1) { }
202 :
203 : /** Get reason from nested non-oks exception. **/
204 : AttributeReadError(const char * type, const std::string& reason) noexcept : exception (fill(type, reason), 0) { }
205 :
206 0 : virtual ~AttributeReadError() noexcept { }
207 :
208 :
209 : private:
210 :
211 : static std::string fill(const char * value, const char * type, const std::string& reason);
212 : static std::string fill(const char * type, const std::string& reason);
213 :
214 : };
215 :
216 :
217 : /** Failed to set attribute or relationship value. **/
218 :
219 : class ObjectSetError : public exception {
220 :
221 : public:
222 :
223 : /** Get reason from nested oks exception. **/
224 0 : ObjectSetError(const OksObject * obj, bool is_rel, const std::string& name, const exception& reason) noexcept : exception (fill(obj, is_rel, name, reason.what()), reason.level() + 1) { }
225 :
226 : /** Get reason from nested non-oks exception. **/
227 0 : ObjectSetError(const OksObject * obj, bool is_rel, const std::string& name, const std::string& reason) noexcept : exception (fill(obj, is_rel, name, reason), 0) { }
228 :
229 0 : virtual ~ObjectSetError() noexcept { }
230 :
231 :
232 : private:
233 :
234 : static std::string fill(const OksObject * obj, bool is_rel, const std::string& name, const std::string& reason);
235 :
236 : };
237 :
238 :
239 : /** Failed to get attribute or relationship value. **/
240 :
241 : class ObjectGetError : public exception {
242 :
243 : public:
244 :
245 : /** Get reason from nested oks exception. **/
246 : ObjectGetError(const OksObject * obj, bool is_rel, const std::string& name, const exception& reason) noexcept : exception (fill(obj, is_rel, name, reason.what()), reason.level() + 1) { }
247 :
248 : /** Get reason from nested non-oks exception. **/
249 0 : ObjectGetError(const OksObject * obj, bool is_rel, const std::string& name, const std::string& reason) noexcept : exception (fill(obj, is_rel, name, reason), 0) { }
250 :
251 0 : virtual ~ObjectGetError() noexcept { }
252 :
253 :
254 : private:
255 :
256 : static std::string fill(const OksObject * obj, bool is_rel, const std::string& name, const std::string& reason);
257 :
258 : };
259 :
260 :
261 : /** Failed to init object. **/
262 :
263 : class ObjectInitError : public exception {
264 :
265 : public:
266 :
267 : /** Get reason from nested oks exception. **/
268 0 : ObjectInitError(const OksObject * obj, const std::string& why, const exception& reason) noexcept : exception (fill(obj, why, reason.what()), reason.level() + 1) { }
269 :
270 : /** Get reason from nested non-oks exception. **/
271 : ObjectInitError(const OksObject * obj, const std::string& why, const std::string& reason) noexcept : exception (fill(obj, why, reason), 0) { }
272 :
273 0 : virtual ~ObjectInitError() noexcept { }
274 :
275 :
276 : private:
277 :
278 : static std::string fill(const OksObject * obj, const std::string& why, const std::string& reason);
279 :
280 : };
281 :
282 :
283 :
284 : /** Failed to init object. **/
285 :
286 : class ObjectBindError : public exception {
287 :
288 : public:
289 :
290 : /** Get reason from nested oks exception. **/
291 0 : ObjectBindError(const OksObject * obj, const OksData * data, const OksRelationship * rel, bool is_error, const std::string& why, const exception& reason) noexcept :
292 0 : exception (fill(obj, rel, why, reason.what()), reason.level() + 1),
293 0 : p_data(data), p_is_error(is_error) { }
294 :
295 : /** Get reason from nested non-oks exception. **/
296 138 : ObjectBindError(const OksObject * obj, const OksData * data, const OksRelationship * rel, bool is_error, const std::string& why, const std::string& reason) noexcept :
297 138 : exception (fill(obj, rel, why, reason), 0),
298 138 : p_data(data), p_is_error(is_error) { }
299 :
300 138 : virtual ~ObjectBindError() noexcept { }
301 :
302 : const OksData * p_data;
303 : const OksRelationship * p_rel;
304 : bool p_is_error;
305 :
306 : private:
307 :
308 : std::string fill(const OksObject * obj, const OksRelationship * rel, const std::string& why, const std::string& reason);
309 :
310 : };
311 :
312 :
313 :
314 : /** Failed to add RCR value. **/
315 :
316 : class AddRcrError : public exception {
317 :
318 : public:
319 :
320 : /** Get reason from nested non-oks exception. **/
321 0 : AddRcrError(const OksObject * obj, const std::string& name, const OksObject * p1, const OksObject * p2) noexcept : exception (fill(obj, name, p1, p2), 0) { }
322 :
323 0 : virtual ~AddRcrError() noexcept { }
324 :
325 :
326 : private:
327 :
328 : static std::string fill(const OksObject * obj, const std::string& name, const OksObject * p1, const OksObject * p2);
329 :
330 : };
331 :
332 :
333 :
334 : /// Struct OKS data information.
335 : /**
336 : * @ingroup oks
337 : *
338 : * The struct OksDataInfo stores information about offset of attribute
339 : * or relationship value (i.e. OksData) inside DATA array
340 : */
341 :
342 : struct OksDataInfo {
343 :
344 : /// Declare map of pointers to OksDataInfo (unsorted by name)
345 :
346 : typedef std::map<std::string, OksDataInfo *> Map;
347 :
348 :
349 : /// Constructors
350 :
351 15356 : OksDataInfo(size_t o, const OksAttribute * a) : offset (o), attribute (a), relationship(nullptr) { ; }
352 10250 : OksDataInfo(size_t o, const OksRelationship * r) : offset (o), attribute (nullptr), relationship(r) { ; }
353 :
354 : size_t offset; // offset of OKS data in the object
355 : const OksAttribute * attribute;
356 : const OksRelationship * relationship;
357 : };
358 :
359 :
360 : /// Class OKS string.
361 : /**
362 : * @ingroup oks
363 : *
364 : * The class OksString is inherited from C++ Standard Library
365 : * string class but uses private memory allocator for instances
366 : * (is used for performance optimisation)
367 : */
368 :
369 : class OksString : public std::string {
370 : friend class OksKernel; /// to deallocate memory when destroyed
371 :
372 : public:
373 :
374 5519 : OksString () {;}
375 1272 : OksString (const std::string& s) : std::string(s) {;}
376 9 : OksString (const char * s) : std::string(s) {;}
377 3639 : OksString (const char * s, size_t n) : std::string(s,n) {;}
378 159 : OksString (const std::string&s, std::string::size_type n) : std::string(s,0,n) {;}
379 :
380 16258 : void * operator new(size_t) {return boost::fast_pool_allocator<OksString>::allocate();}
381 16019 : void operator delete(void *ptr) {boost::fast_pool_allocator<OksString>::deallocate(reinterpret_cast<OksString*>(ptr));}
382 : };
383 :
384 :
385 : /// Implementation of OksString logical equality operator
386 :
387 : inline bool
388 0 : operator==(const OksString& s1, const OksString& s2)
389 : {
390 0 : return ( *(static_cast<const std::string *>(&s1)) == *(static_cast<const std::string *>(&s2)) );
391 : }
392 :
393 :
394 : /// Implementation of OksString logical equality operator
395 :
396 : inline bool
397 : operator==(const OksString& s1, const std::string& s2)
398 : {
399 : return ( *(static_cast<const std::string *>(&s1)) == s2 );
400 : }
401 :
402 :
403 : /// Implementation of OksString logical equality operator
404 :
405 : inline bool
406 : operator==(const OksString& s1, const char *s2)
407 : {
408 : return (*(static_cast<const std::string *>(&s1)) == s2);
409 : }
410 :
411 :
412 : /// Implementation of OksString logical less operator
413 :
414 : inline bool
415 0 : operator<(const OksString& s1, const OksString& s2)
416 : {
417 0 : return ( *(static_cast<const std::string *>(&s1)) < *(static_cast<const std::string *>(&s2)) );
418 : }
419 :
420 :
421 : /// Implementation of OksString out stream operator
422 :
423 : inline std::ostream&
424 0 : operator<<(std::ostream& s, const OksString& str)
425 : {
426 0 : s << *(static_cast<const std::string *>(&str));
427 :
428 0 : return s;
429 : }
430 :
431 :
432 : // forward declaration for private OKS structures declared in non-installing src/oks_utils.hpp
433 :
434 : struct ReloadObjects; ///< the structure for efficient search of objects to be re-read or to be deleted during reload
435 : struct ReadFileParams; ///< the structure to pass common parameters to various read() methods of OksData and OksObject class
436 :
437 :
438 : /// Struct OKS data.
439 : /**
440 : * @ingroup oks
441 : *
442 : * The struct OksData is used to present OKS data types
443 : * (the type is unknown before run-time)
444 : * Members:
445 : * enumeration 'type' is used to define data type in run-time
446 : * union 'data' is used to represent such type
447 : */
448 :
449 : struct OksData {
450 : friend class OksObject;
451 : friend class OksKernel;
452 :
453 : public:
454 :
455 : typedef std::list<OksData *, boost::fast_pool_allocator<OksData *> > List;
456 :
457 : enum Type {
458 : unknown_type = 0,
459 : s8_int_type = 1,
460 : u8_int_type = 2,
461 : s16_int_type = 3,
462 : u16_int_type = 4,
463 : s32_int_type = 5,
464 : u32_int_type = 6,
465 : s64_int_type = 7,
466 : u64_int_type = 8,
467 : float_type = 9,
468 : double_type = 10,
469 : bool_type = 11,
470 : class_type = 12,
471 : object_type = 13,
472 : date_type = 14,
473 : time_type = 15,
474 : string_type = 16,
475 : list_type = 17,
476 : uid_type = 18,
477 : uid2_type = 19,
478 : enum_type = 20
479 : } type;
480 :
481 : union Data {
482 : int8_t S8_INT;
483 : uint8_t U8_INT;
484 : int16_t S16_INT;
485 : uint16_t U16_INT;
486 : int32_t S32_INT;
487 : uint32_t U32_INT;
488 : int64_t S64_INT;
489 : uint64_t U64_INT;
490 : float FLOAT;
491 : double DOUBLE;
492 : bool BOOL;
493 : const OksClass * CLASS;
494 : OksObject * OBJECT;
495 : uint32_t DATE; // boost::gregorian::date => ugly, but member with constructor not allowed in union
496 : uint64_t TIME; // boost::posix_time::ptime => ......................................................
497 : OksString * STRING;
498 : List * LIST;
499 : struct {
500 : const OksClass * class_id;
501 : OksString * object_id;
502 : } UID;
503 : struct {
504 : OksString * class_id;
505 : OksString * object_id;
506 : } UID2;
507 : const std::string * ENUMERATION;
508 : } data;
509 :
510 45497 : OksData() {Clear2();}
511 0 : OksData(int8_t c) {Clear2(); Set(c);}
512 0 : OksData(uint8_t c) {Clear2(); Set(c);}
513 0 : OksData(int16_t i) {Clear2(); Set(i);}
514 0 : OksData(uint16_t i) {Clear2(); Set(i);}
515 2 : OksData(int32_t i) {Clear2(); Set(i);}
516 0 : OksData(uint32_t i) {Clear2(); Set(i);}
517 0 : OksData(int64_t i) {Clear2(); Set(i);}
518 0 : OksData(uint64_t i) {Clear2(); Set(i);}
519 0 : OksData(const float& f) {Clear2(); Set(f);}
520 0 : OksData(const double& d) {Clear2(); Set(d);}
521 0 : OksData(bool b) {Clear2(); Set(b);}
522 0 : OksData(boost::gregorian::date d) {Clear2(); Set(d);}
523 : OksData(boost::posix_time::ptime t) {Clear2(); Set(t);}
524 : OksData(OksString *s) {Clear2(); Set(s);}
525 0 : OksData(const char *s) {Clear2(); Set(s);}
526 6 : OksData(const std::string &s) {Clear2(); Set(s);}
527 : OksData(const OksString &s) {Clear2(); Set(s);}
528 : OksData(const char *s, size_t len, const OksAttribute *a) {Clear2(); SetE(s,len,a);}
529 : OksData(const std::string &s, const OksAttribute *a){Clear2(); SetE(s,a);}
530 : OksData(const OksString &s, const OksAttribute *a) {Clear2(); SetE(s,a);}
531 : OksData(const OksClass * c) {Clear2(); Set(c);}
532 8 : OksData(List *l) {Clear2(); Set(l);}
533 19 : OksData(OksObject *o) {Clear2(); Set(o);}
534 : OksData(const OksClass *c, const char * o) {Clear(); Set(c, o);}
535 : OksData(const OksClass *c, const OksString& o) {Clear(); Set(c, o);}
536 0 : OksData(const std::string &c, const std::string &o) {Clear2(); Set(c, o);}
537 :
538 52571 : ~OksData() {Clear();}
539 :
540 : void Clear();
541 49732 : void Clear2() {type = unknown_type;}
542 :
543 0 : void Set(int8_t c) {Clear(); type = s8_int_type; data.S8_INT = c;}
544 5 : void Set(uint8_t c) {Clear(); type = u8_int_type; data.U8_INT = c;}
545 14 : void Set(int16_t i) {Clear(); type = s16_int_type; data.S16_INT = i;}
546 653 : void Set(uint16_t i) {Clear(); type = u16_int_type; data.U16_INT = i;}
547 102 : void Set(int32_t i) {Clear(); type = s32_int_type; data.S32_INT = i;}
548 2295 : void Set(uint32_t i) {Clear(); type = u32_int_type; data.U32_INT = i;}
549 0 : void Set(int64_t i) {Clear(); type = s64_int_type; data.S64_INT = i;}
550 5 : void Set(uint64_t i) {Clear(); type = u64_int_type; data.U64_INT = i;}
551 20 : void Set(const float& f) {Clear(); type = float_type; data.FLOAT = f;}
552 0 : void Set(const double& d) {Clear(); type = double_type; data.DOUBLE = d;}
553 666 : void Set(bool b) {Clear(); type = bool_type; data.BOOL = b;}
554 : void SetFast(boost::gregorian::date d);
555 : void SetFast(boost::posix_time::ptime t);
556 0 : void Set(boost::gregorian::date d) {Clear(); type = date_type; SetFast(d);}
557 0 : void Set(boost::posix_time::ptime t) {Clear(); type = time_type; SetFast(t);}
558 : void Set(OksString *s) {Clear(); type = string_type; data.STRING = s;}
559 0 : void Set(const char *s) {Clear(); type = string_type; data.STRING = new OksString(s);}
560 6 : void Set(const std::string &s) {Clear(); type = string_type; data.STRING = new OksString(s);}
561 : void Set(const OksString &s) {Clear(); type = string_type; data.STRING = new OksString(s);}
562 : void Set(const OksClass * c) {Clear(); type = class_type; data.CLASS = c;}
563 : inline void SetE(OksString *s, const OksAttribute *a);
564 : inline void SetE(const char *s, size_t len, const OksAttribute *a);
565 : inline void SetE(const std::string &s, const OksAttribute *a);
566 : inline void SetE(const OksAttribute *a);
567 : inline void SetE(const OksString &s, const OksAttribute *a);
568 1542 : void Set(List * l) {Clear(); type = list_type; data.LIST = l;}
569 5421 : void Set(OksObject *o) {Clear(); type = object_type; data.OBJECT = o;}
570 0 : void Set(const OksClass *c, const OksString& s) {Clear(); type = uid_type; data.UID.class_id = c; data.UID.object_id = new OksString(s);}
571 3132 : void Set(const OksClass *c, OksString* s) {Clear(); type = uid_type; data.UID.class_id = c; data.UID.object_id = s;}
572 0 : void Set(const OksString &c, const OksString &s) {Clear(); type = uid2_type; data.UID2.class_id = new OksString(c); data.UID2.object_id = new OksString(s);}
573 0 : void Set(OksString *c, OksString *s) {Clear(); type = uid2_type; data.UID2.class_id = c; data.UID2.object_id = s;}
574 :
575 : /**
576 : * Read from string using non multi-value type
577 : * \throw oks::AttributeReadError is thrown in case of problems.
578 : */
579 : inline void ReadFrom(const char *, Type, const OksAttribute *);
580 :
581 : /**
582 : * Read from string using non multi-value type
583 : * \throw oks::AttributeReadError is thrown in case of problems.
584 : */
585 : inline void ReadFrom(const std::string&, const OksAttribute *);
586 :
587 : /**
588 : * Read from null string (single-value)
589 : * \throw oks::AttributeReadError is thrown in case of problems.
590 : */
591 : void SetNullValue(const OksAttribute * a);
592 :
593 : /**
594 : * Read from string (single-value)
595 : * \throw oks::AttributeReadError is thrown in case of problems.
596 : */
597 : void SetValue(const char * s, const OksAttribute * a);
598 :
599 : /**
600 : * Read from string (any type)
601 : * \throw oks::AttributeReadError is thrown in case of problems.
602 : */
603 : void SetValues(const char *, const OksAttribute * a);
604 :
605 : /**
606 : * Create emtpy list or empty uid2
607 : */
608 : void ReadFrom(const OksRelationship *) noexcept;
609 :
610 : void WriteTo(OksXmlOutputStream&, bool) const;
611 :
612 : void WriteTo(OksXmlOutputStream&) const;
613 :
614 : void ConvertTo(OksData *, const OksRelationship *) const;
615 :
616 : boost::gregorian::date date() const noexcept;
617 : boost::posix_time::ptime time() const noexcept;
618 :
619 :
620 : /**
621 : * \brief Convert data to new type.
622 : *
623 : * The method converts this data to the new data using type defined by attribute parameter.
624 : * A single-value can be converted to multi-value conta4ining this single item.
625 : * A multi-value can be converted to single-value using first item from the multi-value.
626 : *
627 : * If data cannot be converted, then the oks::AttributeReadError exception is thrown.
628 : *
629 : * \param to out parameter (new data containing converted value)
630 : * \param attr pointer to OKS kernel (required to read class_type values)
631 : *
632 : * \throw oks::AttributeReadError is thrown in case of problems.
633 : */
634 :
635 : void cvt(OksData * to, const OksAttribute * attr) const;
636 :
637 : std::string str(int base = 0) const;
638 : std::string str(const OksKernel *) const;
639 :
640 :
641 : /**
642 : * \brief Check range of data.
643 : *
644 : * The method checks that the data matches to the range.
645 : * If the data is out of range, the oks::AttributeRangeError exception is thrown.
646 : * If definition of range is bad, then the oks::AttributeReadError exception is thrown.
647 : *
648 : * \param a attribute defining the range (UML syntax, e.g. "A,B,C" or "1..10" or "*..99")
649 : *
650 : * \throw oks::AttributeRangeError or oks::AttributeReadError is thrown in case of problems.
651 : */
652 :
653 : void check_range(const OksAttribute * a) const;
654 :
655 :
656 : /**
657 : * \brief Set value defined by initial value of attribute.
658 : *
659 : * The method checks that the data matches to the range.
660 : * If the data is out of range, the oks::AttributeRangeError exception is thrown.
661 : * If definition of range is bad, then the oks::AttributeReadError exception is thrown.
662 : *
663 : * \param attr the attribute
664 : * \param kernel pointer to OKS kernel (required to read class_type values)
665 : * \param skip_init only required by OksObject::init2() method for optimization
666 : *
667 : * \throw oks::AttributeReadError is thrown in case of problems.
668 : */
669 :
670 : void set_init_value(const OksAttribute * attr, bool skip_init);
671 :
672 11380 : OksData& operator=(const OksData& d)
673 : {
674 11380 : if(&d != this) {
675 11380 : Clear();
676 11380 : copy(d);
677 : }
678 :
679 11379 : return *this;
680 : }
681 :
682 2824 : OksData(const OksData& d)
683 2824 : {
684 2824 : if(&d != this) {
685 2824 : copy(d);
686 : }
687 2824 : }
688 :
689 : bool operator==(const OksData &) const;
690 : bool operator!=(const OksData &) const;
691 : bool operator<=(const OksData &) const; //report incompatible data types
692 : bool operator>=(const OksData &) const; //report incompatible data types
693 : bool operator<(const OksData &) const; //report incompatible data types
694 : bool operator>(const OksData &) const; //report incompatible data types
695 : friend std::ostream& operator<<(std::ostream&, const OksData&);
696 4520 : void* operator new(size_t) {return boost::fast_pool_allocator<OksData>::allocate();}
697 4522 : void operator delete(void *ptr) {boost::fast_pool_allocator<OksData>::deallocate(reinterpret_cast<OksData*>(ptr));}
698 :
699 : void sort(bool ascending = true);
700 :
701 0 : static bool is_object(Type t)
702 : {
703 0 : return (t == object_type || t == uid_type || t == uid2_type);
704 : }
705 :
706 : private:
707 :
708 : void copy(const OksData &);
709 :
710 : bool is_le(const OksData &) const noexcept; // fast version of operator<=(const OksData &)
711 : bool is_ge(const OksData &) const noexcept; // fast version of operator>=(const OksData &)
712 : bool is_l(const OksData &) const noexcept; // fast version of operator<(const OksData &)
713 : bool is_g(const OksData &) const noexcept; // fast version of operator>(const OksData &)
714 :
715 : /// private methods which can be used by OksObject class only
716 :
717 : void read(const oks::ReadFileParams&, const OksAttribute *, int32_t); // read mv attribute
718 : void read(const oks::ReadFileParams&, const OksAttribute *); // read sv attribute
719 : void read(const OksAttribute *, const OksXmlValue&); // read sv attribute for "data" format
720 : void read(const OksAttribute *, const oks::ReadFileParams&); // read mv attribute for "data" format
721 :
722 : void read(const oks::ReadFileParams&, const OksRelationship*, int32_t); // read mv relationship
723 : void read(const oks::ReadFileParams&, const OksRelationship*); // read sv relationship
724 : void read(const OksRelationship *, const OksXmlRelValue&); // read sv relationship for "data" format
725 : void read(const OksRelationship *, const oks::ReadFileParams&); // read mv relationship for "data" format
726 :
727 0 : OksData(const oks::ReadFileParams& params, const OksAttribute * a, int32_t n) {Clear2(); read(params, a, n);}
728 0 : OksData(const oks::ReadFileParams& params, const OksAttribute * a) {Clear2(); read(params, a);}
729 827 : OksData(const OksAttribute * a, const OksXmlValue& value) {Clear2(); read(a, value);}
730 0 : OksData(const OksAttribute * a, const oks::ReadFileParams& params) {Clear2(); read(a, params);}
731 :
732 0 : OksData(const oks::ReadFileParams& params, const OksRelationship *r, int32_t n) {Clear2(); read(params, r, n);}
733 0 : OksData(const oks::ReadFileParams& params, const OksRelationship *r) {Clear2(); read(params, r);}
734 3380 : OksData(const OksRelationship * r, const OksXmlRelValue& value) {Clear2(); read(r, value);}
735 0 : OksData(const OksRelationship * r, const oks::ReadFileParams& params) {Clear2(); read(r, params);}
736 :
737 : void WriteTo(OksXmlOutputStream&, OksKernel *, OksAliasTable *, bool, bool) const;
738 :
739 : bool IsConsistent(const OksRelationship *r, const OksObject *o, const char *msg);
740 :
741 : const std::string& __oid() const;
742 : const std::string& __cn() const;
743 : };
744 :
745 :
746 : inline void
747 30 : OksData::ReadFrom(const char * s, Type t, const OksAttribute * a)
748 : {
749 30 : Clear();
750 30 : type = t;
751 30 : SetValue(s, a);
752 30 : }
753 :
754 :
755 : /**
756 : * @ingroup oks
757 : *
758 : * \brief The struct OksRCR describes Reverse Composite Relationship
759 : * (i.e. back reference from child to composite parent)
760 : */
761 :
762 : struct OksRCR {
763 : friend class OksKernel;
764 :
765 : public:
766 :
767 2623 : OksRCR (OksObject *o, const OksRelationship *r) :
768 2623 : obj (o), relationship (r) {;}
769 :
770 2623 : void * operator new(size_t) {return boost::fast_pool_allocator<OksRCR>::allocate();}
771 2623 : void operator delete(void *ptr) {boost::fast_pool_allocator<OksRCR>::deallocate(reinterpret_cast<OksRCR*>(ptr));}
772 :
773 : OksObject * obj;
774 : const OksRelationship * relationship;
775 :
776 : };
777 :
778 : struct hash_str
779 : {
780 13055 : inline size_t operator() ( const std::string * x ) const {
781 13055 : return std::hash<std::string>()(*x);
782 : }
783 : };
784 :
785 : struct equal_str
786 : {
787 5509 : inline bool operator()(const std::string * __x, const std::string * __y) const {
788 5509 : return ((__x == __y) || (*__x == *__y));
789 : }
790 : };
791 :
792 : struct hash_obj_ptr
793 : {
794 20 : inline size_t operator() ( const OksObject * x ) const {
795 20 : return reinterpret_cast<size_t>(x);
796 : }
797 : };
798 :
799 : struct equal_obj_ptr
800 : {
801 0 : inline bool operator()(const OksObject * __x, const OksObject * __y) const {
802 0 : return (__x == __y);
803 : }
804 : };
805 :
806 : struct hash_class_ptr
807 : {
808 0 : inline size_t operator() ( const OksClass * x ) const {
809 0 : return reinterpret_cast<size_t>(x);
810 : }
811 : };
812 :
813 : struct equal_class_ptr
814 : {
815 0 : inline bool operator()(const OksClass * __x, const OksClass * __y) const {
816 0 : return (__x == __y);
817 : }
818 : };
819 :
820 : typedef std::unordered_set<const OksClass *, oks::hash_class_ptr, oks::equal_class_ptr> ClassSet;
821 :
822 :
823 : /**
824 : * @ingroup oks
825 : *
826 : * \brief OksObject describes instance of OksClass
827 : *
828 : * This class implements OKS object that is an instance of OKS class.
829 : * Each object has unique ID string in a scope of class and its derived sub-classes.
830 : * The properties of object are described by values of its attributes (i.e. values of
831 : * primitive types like strings, integers, floats, see also OksAttribute)
832 : * and relationships (i.e. references on others OKS objects, see also OksRelationship).
833 : */
834 :
835 : class OksObject
836 : {
837 : friend class OksClass;
838 : friend struct OksData;
839 : friend class OksKernel;
840 : friend class OksIndex;
841 : friend class OksObjectSortBy;
842 : friend struct OksLoadObjectsJob;
843 : friend struct oks::ReadFileParams;
844 : friend struct oks::ReloadObjects;
845 :
846 : public:
847 :
848 : typedef void (*notify_obj)(OksObject *, void *);
849 :
850 : /** Functor to sort map of OksObject pointers by object Id */
851 :
852 : struct SortById {
853 0 : bool operator() (const std::string * s1, const std::string * s2) const {
854 0 : return *s1 < *s2;
855 : }
856 : };
857 :
858 : /** Map of pointers to OksObject sorted by object Id */
859 :
860 : typedef std::map<const std::string *, OksObject *, SortById> SMap;
861 :
862 :
863 : /** Map of pointers to OksObject (unsorted) */
864 :
865 : typedef std::unordered_map<const std::string *, OksObject *, oks::hash_str, oks::equal_str> Map;
866 : typedef std::unordered_set<OksObject *, oks::hash_obj_ptr, oks::equal_obj_ptr> FSet;
867 :
868 :
869 : /** Set of pointers to OksObject */
870 :
871 : typedef std::set<OksObject *, std::less<OksObject *> > Set;
872 :
873 : /** List of pointers to OksObject */
874 :
875 : typedef std::list<OksObject *> List;
876 :
877 : typedef std::list<OksObject *, boost::fast_pool_allocator<OksObject *> > FList;
878 :
879 :
880 : /**
881 : * \brief OKS object constructor.
882 : *
883 : * Create new OKS object providing class and object ID.
884 : * If the object ID is not set, the OKS creates new object with random unique ID.
885 : * To create a new object the OKS kernel active data file has to be set.
886 : *
887 : * In case of problems the error message is printed and the uid.class_id is set to 0 to flag the error.
888 : *
889 : * The parameters are:
890 : * \param oks_class pointer to OKS class
891 : * \param object_id optional object unique ID
892 : * \param skip_init if true, skip initialization of OKS data
893 : */
894 :
895 : OksObject (const OksClass * oks_class, const char * object_id = 0, bool skip_init = false);
896 :
897 :
898 : /**
899 : * \brief OKS object copy constructor.
900 : *
901 : * Create new OKS object as copy of parent.
902 : * If the object ID is not set, the OKS creates new object with random unique ID.
903 : * To create a new object the OKS kernel active data file has to be set.
904 : *
905 : * In case of problems the error message is printed and the uid.class_id is set to 0 to flag the error.
906 : *
907 : * The parameters are:
908 : * \param parent_object pointer to OKS class
909 : * \param object_id optional object unique ID
910 : */
911 :
912 : OksObject (const OksObject & parent_object, const char * object_id = 0);
913 :
914 :
915 : /**
916 : * \brief Destroy OKS object.
917 : *
918 : * This the the only way available to user to destroy OKS object since ~OksObject() is private.
919 : *
920 : * When an object is destroyed, it shall not be referenced by other objects.
921 : *
922 : * In case of problems the oks::exception is thrown.
923 : *
924 : * The parameters are:
925 : * \param obj the object to be destroyed
926 : * \param fast if true, skip extra protection checks
927 : */
928 :
929 : static void destroy(OksObject * obj, bool fast = false);
930 :
931 :
932 : /**
933 : * \brief The equality operator.
934 : *
935 : * The operator returns true, if comparing objects belong to the same class
936 : * or classes with equal names (e.g. belonging to different OksKernels)
937 : * and their attributes and relationships are equal.
938 : */
939 :
940 : bool operator==(const OksObject&) const;
941 :
942 :
943 : /**
944 : * \brief The fast equal method.
945 : *
946 : * This method replaces operator!= used by OKS library in the past,
947 : * since the operator causes problems starting from gcc62 assuming &reference != nullptr
948 : *
949 : * The method returns false, if comparing objects belong to classes with different names or their IDs are not equal.
950 : */
951 :
952 : static bool
953 : are_equal_fast(const OksObject * o1, const OksObject * o2);
954 :
955 : bool operator!=(const OksObject&) const = delete;
956 :
957 :
958 : /** Fast new operator to reduce resources consumption. */
959 :
960 4333 : void * operator new(size_t) {return boost::fast_pool_allocator<OksObject>::allocate();}
961 :
962 :
963 : /** Fast delete operator. */
964 :
965 4334 : void operator delete(void *ptr) {boost::fast_pool_allocator<OksObject>::deallocate(reinterpret_cast<OksObject*>(ptr));}
966 :
967 :
968 : /**
969 : * \brief Detailed stream operator.
970 : *
971 : * Send to stream complete description of OKS object:
972 : * - print class name and ID
973 : * - print value of all attributes and relationships
974 : */
975 :
976 : friend std::ostream& operator<<(std::ostream& out, const OksObject & obj);
977 :
978 :
979 : /**
980 : * \brief Short stream operator.
981 : *
982 : * Send to stream OKS object reference in format "foo@bar" (i.e. object "foo" from class "bar")
983 : */
984 :
985 : friend std::ostream& operator<<(std::ostream&, const OksObject *);
986 :
987 :
988 : /** Get class of object. */
989 :
990 1581 : const OksClass * GetClass() const {return uid.class_id;}
991 :
992 :
993 : /** Get object ID. */
994 :
995 2707 : const std::string& GetId() const {return uid.object_id;}
996 :
997 :
998 : /**
999 : * \brief Set object ID.
1000 : *
1001 : * The ID has to be unique in scope of object's class
1002 : * and all classes participating in inheritance hierarchy of this class.
1003 : *
1004 : * \param id new identity of the object
1005 : * In case of problems the oks::exception is thrown.
1006 : */
1007 :
1008 : void set_id(const std::string & id);
1009 :
1010 :
1011 : /** Get file of object. */
1012 :
1013 0 : OksFile * get_file() const {return file;}
1014 :
1015 :
1016 : /**
1017 : * \brief Move object to different file.
1018 : *
1019 : * Move object to an existing file. Both, present file where object is stored
1020 : * and new destination file have to be writable by user.
1021 : *
1022 : * The parameters are:
1023 : * \param file destination file
1024 : * \param update_owner mark original file as updated
1025 : *
1026 : * \throw oks::exception is thrown in case of problems.
1027 : */
1028 :
1029 : void set_file(OksFile * file, bool update_owner = true);
1030 :
1031 :
1032 : /**
1033 : * \brief Get value of attribute by name.
1034 : *
1035 : * The method returns pointer on OksData value for given attribute.
1036 : *
1037 : * In case of problems (e.g. no attribute with such name) the oks::exception is thrown.
1038 : *
1039 : * The parameter is:
1040 : * \param name name of attribute
1041 : *
1042 : * \return the OKS data value for given attribute
1043 : *
1044 : * \throw oks::exception is thrown in case of problems.
1045 : */
1046 :
1047 : OksData * GetAttributeValue(const std::string& name) const;
1048 :
1049 :
1050 : /**
1051 : * \brief Get value of attribute by offset.
1052 : *
1053 : * The method returns pointer on OksData value for given attribute offset.
1054 : * The method is optimised for performance and does not check validity of offset.
1055 : *
1056 : * The parameter is:
1057 : * \param data_info describes offset of attribute's value for given OKS class
1058 : *
1059 : * \return the OKS data value for given attribute
1060 : */
1061 :
1062 2488 : OksData * GetAttributeValue(const OksDataInfo *i) const noexcept { return &(data[i->offset]); }
1063 :
1064 :
1065 : /**
1066 : * \brief Get value of relationship by name.
1067 : *
1068 : * The method returns pointer on OksData value for given relationship.
1069 : *
1070 : * In case of problems (e.g. no relationship with such name) the oks::exception is thrown.
1071 : *
1072 : * The parameter is:
1073 : * \param name name of relationship
1074 : *
1075 : * \return the OKS data value for given relationship
1076 : *
1077 : * \throw oks::exception is thrown in case of problems.
1078 : */
1079 :
1080 : OksData * GetRelationshipValue(const std::string&) const;
1081 :
1082 :
1083 : /**
1084 : * \brief Get value of relationship by offset.
1085 : *
1086 : * The method returns pointer on OksData value for given relationship offset.
1087 : * The method is optimised for performance and does not check validity of offset.
1088 : *
1089 : * The parameter is:
1090 : * \param data_info describes offset of relationship's value for given OKS class
1091 : *
1092 : * \return the OKS data value for given relationship
1093 : */
1094 :
1095 1254 : OksData * GetRelationshipValue(const OksDataInfo *i) const noexcept { return &(data[i->offset]); }
1096 :
1097 :
1098 : /**
1099 : * \brief Set value of attribute by name.
1100 : *
1101 : * It the type of data do not match to the defined by the attribute of object's class,
1102 : * then the method tries to convert them and to print out warning message.
1103 : *
1104 : * In case of problems (e.g. no attribute with such name, data are out of range) the oks::exception is thrown.
1105 : *
1106 : * The parameters are:
1107 : * \param name name of attribute
1108 : * \param data new attribute value
1109 : *
1110 : * \throw oks::exception is thrown in case of problems.
1111 : */
1112 :
1113 : void SetAttributeValue(const std::string& name, OksData * data);
1114 :
1115 :
1116 : /**
1117 : * \brief Set value of attribute by offset.
1118 : *
1119 : * It the type of data do not match to the defined by the attribute of object's class,
1120 : * then the method tries to convert them and to print out warning message.
1121 : *
1122 : * In case of problems (e.g. data are out of range) the oks::exception is thrown.
1123 : *
1124 : * The parameters are:
1125 : * \param data_info describes offset of attribute's value for given OKS class
1126 : * \param data new attribute value
1127 : *
1128 : * \throw oks::exception is thrown in case of problems.
1129 : */
1130 :
1131 : void SetAttributeValue(const OksDataInfo * data_info, OksData * data);
1132 :
1133 :
1134 : /**
1135 : * \brief Set value of relationship by name.
1136 : *
1137 : * In case of problems (e.g. no relationship with such name, wrong class type or cardinality constraint) the oks::exception is thrown.
1138 : *
1139 : * The parameters are:
1140 : * \param name name of relationship
1141 : * \param data new relationship value
1142 : * \param skip_non_null_check if true, ignore low cardinality constraint
1143 : *
1144 : * \throw oks::exception is thrown in case of problems.
1145 : */
1146 :
1147 : void SetRelationshipValue(const std::string& name, OksData * data, bool skip_non_null_check = false);
1148 :
1149 :
1150 : /**
1151 : * \brief Set value of relationship by offset.
1152 : *
1153 : * In case of problems (e.g. wrong class type or cardinality constraint) the oks::exception is thrown.
1154 : *
1155 : * The parameters are:
1156 : * \param data_info describes offset of relationship's value for given OKS class
1157 : * \param data new relationship value
1158 : * \param skip_non_null_check if true, ignore low cardinality constraint
1159 : *
1160 : * \throw oks::exception is thrown in case of problems.
1161 : */
1162 :
1163 : void SetRelationshipValue(const OksDataInfo * data_info, OksData * data, bool skip_non_null_check = false);
1164 :
1165 :
1166 : /**
1167 : * \brief Set value of single-value relationship by name.
1168 : *
1169 : * In case of problems (e.g. no relationship with such name, wrong class type or relationship is multi-value) the oks::exception is thrown.
1170 : *
1171 : * The parameters are:
1172 : * \param name name of relationship
1173 : * \param object new relationship value
1174 : *
1175 : * \throw oks::exception is thrown in case of problems.
1176 : */
1177 :
1178 : void SetRelationshipValue(const std::string& name, OksObject * object);
1179 :
1180 :
1181 : /**
1182 : * \brief Set value of single-value relationship by offset.
1183 : *
1184 : * In case of problems (e.g. wrong class type or relationship is multi-value) the oks::exception is thrown.
1185 : *
1186 : * The parameters are:
1187 : * \param data_info describes offset of relationship's value for given OKS class
1188 : * \param object new relationship value
1189 : *
1190 : * \throw oks::exception is thrown in case of problems.
1191 : */
1192 :
1193 : void SetRelationshipValue(const OksDataInfo * data_info, OksObject * object);
1194 :
1195 :
1196 : /**
1197 : * \brief Add object value to multi-value relationship by name.
1198 : *
1199 : * In case of problems (e.g. no relationship with such name, wrong class type, relationship is single-value or
1200 : * RCR cannot be set) the oks::exception is thrown.
1201 : *
1202 : * The parameters are:
1203 : * \param name name of relationship
1204 : * \param object the object to be added
1205 : *
1206 : * \throw oks::exception is thrown in case of problems.
1207 : */
1208 :
1209 : void AddRelationshipValue(const std::string& name, OksObject * object);
1210 :
1211 :
1212 : /**
1213 : * \brief Add object value to multi-value relationship by offset.
1214 : *
1215 : * In case of problems (e.g. wrong class type, relationship is single-value or RCR cannot be set) the oks::exception is thrown.
1216 : *
1217 : * The parameters are:
1218 : * \param data_info describes offset of relationship's value for given OKS class
1219 : * \param object the object to be added
1220 : *
1221 : * \throw oks::exception is thrown in case of problems.
1222 : */
1223 :
1224 : void AddRelationshipValue(const OksDataInfo * data_info, OksObject * object);
1225 :
1226 :
1227 : /**
1228 : * \brief Remove object value from multi-value relationship by name.
1229 : *
1230 : * In case of problems (e.g. no relationship with such name, relationship is single-value or there is no such object) the oks::exception is thrown.
1231 : *
1232 : * The parameters are:
1233 : * \param name name of relationship
1234 : * \param object the object to be removed from relationship
1235 : *
1236 : * \throw oks::exception is thrown in case of problems.
1237 : */
1238 :
1239 : void RemoveRelationshipValue(const std::string& name, OksObject * object);
1240 :
1241 :
1242 : /**
1243 : * \brief Remove object value from multi-value relationship by offset.
1244 : *
1245 : * In case of problems (e.g. relationship is single-value or there is no such object) the oks::exception is thrown.
1246 : *
1247 : * The parameters are:
1248 : * \param data_info describes offset of relationship's value for given OKS class
1249 : * \param object the object to be removed from relationship
1250 : *
1251 : * \throw oks::exception is thrown in case of problems.
1252 : */
1253 :
1254 : void RemoveRelationshipValue(const OksDataInfo * data_info, OksObject * object);
1255 :
1256 :
1257 : /**
1258 : * \brief Set class-name and object-id value of single-value relationship by name.
1259 : *
1260 : * In case of problems (e.g. no relationship with such name, wrong class type or relationship is multi-value) the oks::exception is thrown.
1261 : *
1262 : * The parameters are:
1263 : * \param rel_name name of relationship
1264 : * \param class_name class name of the referenced object
1265 : * \param object_id ID of the referenced object
1266 : *
1267 : * \throw oks::exception is thrown in case of problems.
1268 : */
1269 :
1270 : void SetRelationshipValue(const std::string& rel_name, const std::string& class_name, const std::string& object_id);
1271 :
1272 :
1273 : /**
1274 : * \brief Add class-name and object-id value to multi-value relationship by name.
1275 : *
1276 : * In case of problems (e.g. no relationship with such name, unknown class) the oks::exception is thrown.
1277 : *
1278 : * The parameters are:
1279 : * \param rel_name name of relationship
1280 : * \param class_name class name of the referenced object
1281 : * \param object_id ID of the referenced object
1282 : *
1283 : * \throw oks::exception is thrown in case of problems.
1284 : */
1285 :
1286 : void AddRelationshipValue(const std::string& rel_name, const std::string& class_name, const std::string& object_i);
1287 :
1288 :
1289 : /**
1290 : * \brief Remove class-name and object-id value from multi-value relationship by name.
1291 : *
1292 : * In case of problems (e.g. no relationship with such name, no such object) the oks::exception is thrown.
1293 : *
1294 : * The parameters are:
1295 : * \param rel_name name of relationship
1296 : * \param class_name class name of the referenced object
1297 : * \param object_id ID of the referenced object
1298 : *
1299 : * \throw oks::exception is thrown in case of problems.
1300 : */
1301 :
1302 : void RemoveRelationshipValue(const std::string& rel_name, const std::string& class_name, const std::string& object_i);
1303 :
1304 :
1305 : /**
1306 : * \brief Return information about composite parents.
1307 : * The method returns list of the OKS object's reverse composite relationships.
1308 : */
1309 :
1310 0 : const std::list<OksRCR *> * reverse_composite_rels() const {return p_rcr;}
1311 :
1312 :
1313 : /**
1314 : * \brief Return objects referencing this one via relationship with given name.
1315 : *
1316 : * The method returns list of objects which have a reference on given one.
1317 : * If the relationship name is set to "*", then the method takes into account all relationships of all objects.
1318 : * The method performs full scan of all OKS objects and it is not recommended at large scale to build complete graph of relations between all database object;
1319 : * if only composite parents are needed, them the reverse_composite_rels() method has to be used.
1320 : *
1321 : * The parameters are:
1322 : * \param name the name of relationship used to reference given object (by default ANY relationship)
1323 : *
1324 : * \return the list of objects referencing this one (can be null, if there are no such objects); the user is responsible to destroy the returned list (but not the objects it contains)
1325 : */
1326 :
1327 : FList * get_all_rels(const std::string& name = "*") const;
1328 :
1329 :
1330 : /**
1331 : * \brief Set transient user data associated with given object.
1332 : * Such data are not stored on file and only exist while OksKernel object is not destroyed.
1333 : */
1334 :
1335 0 : void SetTransientData(void *d) const {p_user_data = d;}
1336 :
1337 :
1338 : /**
1339 : * \brief Get transient user data associated with given object.
1340 : * Return data set using SetTransientData() method.
1341 : */
1342 :
1343 0 : void * GetTransientData() const {return p_user_data;}
1344 :
1345 :
1346 : /**
1347 : * \brief Set object id is used to assign an object unique integer number.
1348 : * Such data are not stored on file and only exist while OksKernel object is not destroyed.
1349 : */
1350 :
1351 : void set_int32_id(int32_t object_id) {p_int32_id = object_id;}
1352 :
1353 : /**
1354 : * \brief Get object id associated with given object.
1355 : * Return integer number set using set_int32_id() method.
1356 : */
1357 :
1358 : int32_t get_int32_id() const {return p_int32_id;}
1359 :
1360 :
1361 :
1362 : /**
1363 : * \brief Check if object satisfies query expression.
1364 : *
1365 : * The method parses query expression structures and applies them to the object's values.
1366 : * In case of incorrect query expression parameter the method throws exception.
1367 : *
1368 : * \param query_exp the query expression
1369 : * \return true, if object satisfies given query expression.
1370 : *
1371 : * \throw std::exception is thrown in case of problems.
1372 : */
1373 :
1374 : bool SatisfiesQueryExpression(OksQueryExpression * query_exp) const;
1375 :
1376 : bool satisfies(const OksObject * goal, const oks::QueryPathExpression& expresssion, OksObject::List& path) const;
1377 : OksObject::List * find_path(const oks::QueryPath& query) const;
1378 :
1379 : /** The method checks the schema constraints for given object and the file's includes. Return false, if object is inconsistent. **/
1380 : bool is_consistent(const std::set<OksFile *>&, const char * msg) const;
1381 :
1382 :
1383 : /** The method returns string containing dangling references for given object. **/
1384 : std::string report_dangling_references() const;
1385 :
1386 : /** The method puts to set objects recursively referenced by given object. **/
1387 : void references(OksObject::FSet& refs, unsigned long recursion_depth, bool add_self = false, oks::ClassSet * classes = 0) const;
1388 :
1389 :
1390 0 : bool is_duplicated() const { return (p_duplicated_object_id_idx != -1); }
1391 :
1392 :
1393 : private:
1394 :
1395 : // the struct OksUid is used to describe object unique identity
1396 : // in form 'class_name@object_identity'
1397 :
1398 : struct OksUid {
1399 : const OksClass * class_id;
1400 : std::string object_id;
1401 :
1402 4334 : OksUid() : class_id(0) {;}
1403 : } uid;
1404 :
1405 : OksData * data;
1406 : std::list<OksRCR *> * p_rcr;
1407 : mutable void * p_user_data;
1408 : int32_t p_int32_id;
1409 : int32_t p_duplicated_object_id_idx;
1410 : OksFile * file;
1411 :
1412 :
1413 : // to be used by OksKernel only
1414 :
1415 : ~OksObject();
1416 :
1417 :
1418 : /**
1419 : * Read OKS object from input stream.
1420 : *
1421 : * \return The method returns a pointer to OksObject, or NULL object to indicate end-of-stream.
1422 : * \throw oks::exception is thrown in case of errors, e.g. bad input stream, duplicated object, abstract class of object.
1423 : **/
1424 :
1425 : static OksObject * read(const oks::ReadFileParams&);
1426 : void __report_type_cvt_warning(const oks::ReadFileParams&, const OksAttribute&, const OksData&, const OksData::Type, int32_t) const;
1427 : void __report_cardinality_cvt_warning(const oks::ReadFileParams&, const OksRelationship&) const;
1428 : int32_t __get_num(const oks::ReadFileParams& params);
1429 :
1430 :
1431 :
1432 : // these two are used by read() method
1433 :
1434 : void read_body(const oks::ReadFileParams&, bool);
1435 :
1436 : /**
1437 : * Construct OKS object from input stream.
1438 : * \throw oks::exception is thrown in case of errors.
1439 : **/
1440 : OksObject (const oks::ReadFileParams&, OksClass *, const std::string&);
1441 :
1442 :
1443 :
1444 : // to be used by OksIndex only
1445 :
1446 : OksObject (size_t, const OksData *);
1447 :
1448 : // to be used by OksKernel only
1449 :
1450 : OksObject (OksClass * c, const std::string& id, void * user_data, int32_t object_id, int32_t duplicated_object_id_idx, OksFile * f);
1451 :
1452 : // is not implemented and must not be used
1453 :
1454 : OksObject& operator= (const OksObject &);
1455 :
1456 :
1457 : // these 3 methods are used by constructors
1458 :
1459 : void init1(const OksFile * = 0);
1460 : void init2(bool skip_init = false);
1461 : void init3();
1462 : void init3(OksClass *c);
1463 :
1464 : void check_ids();
1465 :
1466 :
1467 : public:
1468 :
1469 : void add_RCR(OksObject *, const OksRelationship *);
1470 : void remove_RCR(OksObject *, const OksRelationship *) noexcept;
1471 :
1472 :
1473 : private:
1474 :
1475 17 : inline void notify() {
1476 17 : file->set_updated();
1477 17 : change_notify();
1478 17 : }
1479 :
1480 : void check_class_type(const OksRelationship *, const OksClass *);
1481 19 : void check_class_type(const OksRelationship *r, const OksObject *o) { if(o) { check_class_type(r, o->GetClass()); }}
1482 : void check_non_null(const OksRelationship *, const OksObject *);
1483 : void check_file_lock(const OksAttribute *, const OksRelationship *);
1484 :
1485 :
1486 : void set_unique_id();
1487 : void put(OksXmlOutputStream&, bool force_defaults) const;
1488 : static void put_object_attributes(OksXmlOutputStream&, const OksData&);
1489 :
1490 : // bind data and methods
1491 :
1492 : struct BindInfo {
1493 : OksKernel * k;
1494 : OksObject * o;
1495 : OksRelationship * r;
1496 : };
1497 :
1498 : /** Binds objects and returns true on success **/
1499 :
1500 : void bind_objects();
1501 : static void bind(OksData *, const BindInfo&);
1502 :
1503 : void unbind_file(const OksFile *);
1504 :
1505 :
1506 : // check and report to standard out missing file inclusion paths
1507 :
1508 : bool check_links_and_report(const OksObject *, const std::set<OksFile *>&, const std::string&, const char *) const;
1509 :
1510 :
1511 : // valid names of xml tags and attributes
1512 :
1513 : static const char obj_xml_tag[];
1514 : static const char obj2_xml_tag[];
1515 : static const char attribute_xml_tag[];
1516 : static const char relationship_xml_tag[];
1517 : static const char class_xml_attribute[];
1518 : static const char class2_xml_attribute[];
1519 : static const char id_xml_attribute[];
1520 : static const char id2_xml_attribute[];
1521 : static const char name_xml_attribute[];
1522 : static const char type_xml_attribute[];
1523 : static const char num_xml_attribute[];
1524 :
1525 : static const char value_xml_attribute[];
1526 : static const char data_xml_tag[];
1527 : static const char ref_xml_tag[];
1528 :
1529 : notify_obj get_change_notify() const;
1530 :
1531 : void create_notify();
1532 : void change_notify();
1533 : void delete_notify();
1534 :
1535 : };
1536 :
1537 : } // namespace oks
1538 : } // namespace dunedaq
1539 :
1540 : #endif
|