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