LCOV - code coverage report
Current view: top level - oks/include/oks - object.hpp (source / functions) Coverage Total Hit
Test: code.result Lines: 48.1 % 154 74
Test Date: 2026-07-12 15:23:06 Functions: 43.4 % 122 53

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

Generated by: LCOV version 2.0-1