LCOV - code coverage report
Current view: top level - oks/include/oks - object.hpp (source / functions) Coverage Total Hit
Test: code.result Lines: 46.3 % 408 189
Test Date: 2026-10-11 15:05:20 Functions: 44.3 % 122 54

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

Generated by: LCOV version 2.0-1