LCOV - code coverage report
Current view: top level - oks/include/oks - object.hpp (source / functions) Coverage Total Hit
Test: code.result Lines: 47.4 % 154 73
Test Date: 2025-12-21 13:07:08 Functions: 42.6 % 122 52

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

Generated by: LCOV version 2.0-1