56 s <<
"Failed to read \'" <<
what <<
"\' of object " << o <<
'\n' << reason;
64 s <<
"Failed to create object " << o <<
'\n' << reason;
72 s <<
"Failed to save object " << o <<
'\n' << reason;
80 s <<
"Failed to rename object " << o <<
'\n' << reason;
88 s <<
"Failed to destroy object " << o <<
'\n' << reason;
96 s <<
"Failed to set " << (is_rel ?
"relationship" :
"attribute") <<
" \'" << name <<
"\' of object " << obj <<
'\n' << reason;
103 std::ostringstream s;
104 s <<
"Failed to get " << (is_rel ?
"relationship" :
"attribute") <<
" \'" << name <<
"\' of object " << obj <<
'\n' << reason;
111 std::ostringstream s;
112 s <<
"Object " << obj <<
" cannot be linked with " << p1 <<
" via exclusive relationship \'" << name <<
"\' since it is already referenced by object " << p2;
119 std::ostringstream s;
120 s <<
"Failed to init object " << obj <<
" because " << why <<
'\n' << reason;
128 std::ostringstream s;
129 s <<
"Failed to bind relationship";
131 s <<
" of object " << obj <<
" because:\n" << why;
132 if(!reason.empty()) s <<
'\n' << reason;
145 std::lock_guard lock(
uid.class_id->p_unique_id_mutex);
149 for (
unsigned long i = 0; i < 0xFFFFFFFF; ++i)
151 sprintf(unique_id.get(),
"%s^%lu",
uid.object_id.c_str(), i);
152 std::string id(unique_id.get());
153 if(
uid.class_id->get_object(
id) ==
nullptr)
164 if (std::vector<OksClass *> * cs =
uid.class_id->p_inheritance_hierarchy)
166 for (std::vector<OksClass *>::const_iterator j = cs->begin(); j != cs->end(); ++j)
169 if (__builtin_expect((o !=
nullptr), 0))
173 "has ID equal with \'" <<
uid.object_id <<
'@' <<
uid.class_id->get_name() <<
"\' object and their classes belong to the same inheritance hierarchy "
174 "(the OKS kernel is configured in the \"test-duplicated-objects-within-inheritance-hierarchy\" mode for compatibility with config and DAL tools)";
185 const std::string & object_id =
uid.object_id;
186 const OksKernel * kernel(c->get_kernel());
191 if( __builtin_expect((c->get_is_abstract()), 0) ) {
192 std::ostringstream text;
193 text <<
"the class \'" << c->get_name() <<
"\' is abstract";
200 if( __builtin_expect((!object_id.empty()), 1) ) {
205 OksObject * o = c->get_object(object_id);
207 if( __builtin_expect((o !=
nullptr), 0) ) {
212 <<
"WARNING [OksObject constructor]:\n"
213 " Cannot create object " << o;
219 " Skip above problem since OKS kernel is configured in \'ignore-duplicated-objects\' mode\n"
220 <<
" Create duplicated object with ID = \'" <<
uid.object_id <<
"\'\n";
280 if (c->p_all_attributes)
282 if (skip_init ==
false)
284 for (
const auto& i : *c->p_all_attributes)
285 data[count++] = i->p_init_data;
289 for (
const auto& i : *c->p_all_attributes)
290 data[count++] = i->p_empty_init_data;
294 if(c->p_all_relationships) {
295 for(
const auto& i : *c->p_all_relationships) {
299 d.data.OBJECT =
nullptr;
312 if( __builtin_expect((c->p_indices !=
nullptr), 0) ) {
313 for(
auto& i : *c->p_indices) i.second->insert(
this);
317 c->p_kernel->define(
this);
327#define READ_OBJ_HEADER(F1, S1, F2, S2) \
329 OksXmlAttribute attr(read_params.s); \
330 if(oks::cmp_str1(attr.name(), ">") || oks::cmp_str1(attr.name(), "/")) { break; } \
331 else if(F1(attr.name(), S1)) { \
332 std::shared_lock lock(read_params.oks_kernel->p_schema_mutex); \
333 c = read_params.oks_kernel->find_class(attr.value()); \
334 if( __builtin_expect((c == nullptr), 0) ) { \
335 std::ostringstream text; \
336 text << "cannot find class \"" << attr.value() << "\" (line " \
337 << read_params.s.get_line_no() << ", char " \
338 << read_params.s.get_line_pos() << ')'; \
339 throw std::runtime_error( text.str().c_str() ); \
342 else if(F2(attr.name(), S2)) id.assign(attr.value(), attr.value_len()); \
344 read_params.s.throw_unexpected_attribute(attr.name()); \
380 catch (std::exception & e) {
392 if(read_params.
format !=
'c') {
402 catch (std::exception & e) {
413 catch(std::exception& ex) {
419 o->read_body(read_params,
true);
427 if(c ==
nullptr &&
id.empty()) {
return nullptr; }
439 obj->create_notify();
442 TLOG_DEBUG(3) <<
"*** create object " << obj <<
" while reload data ***";
453 const char * type_str;
472 default: type_str =
"unknown";
479 " convert value from wrong type \"" << (num == -1 ?
"single" :
"multi") <<
"-value " << type_str <<
"\" to \"" << (a.
get_is_multi_values() ?
"multi" :
"single")
480 <<
"-value " << a.
get_type() <<
"\" as required for attribute \"" << a.
get_name() <<
"\"\n"
481 <<
" converted value: " << d << std::endl;
490 " mismatch between relationship \"" << r.get_name() <<
"\" cardinality and its value (save data file with new schema)." << std::endl;
496 std::ostringstream s;
497 s <<
"Unknown attribute type \"" << atype <<
'\"';
506 int32_t num =
static_cast<int32_t
>(strtol(params.
s.
m_cvt_char->
m_buf, &__sanity, 0));
521 bool was_updated =
false;
529 file = read_params.
f;
536 if( __builtin_expect((read_params.
format !=
'c'), 1) ) {
537 OksDataInfo::Map::iterator info_i;
543 std::list<const OksAttribute *> * read_attributes =
nullptr;
544 std::list<const OksRelationship *> * read_relationships =
nullptr;
546 if( __builtin_expect((check_re_read), 0) ) {
547 if(c->p_all_attributes && !c->p_all_attributes->empty()) {
548 read_attributes =
new std::list<const OksAttribute *>();
549 for(
auto& i : *c->p_all_attributes)
550 read_attributes->push_back(i);
553 if(c->p_all_relationships && !c->p_all_relationships->empty()) {
554 read_relationships =
new std::list<const OksRelationship *>();
555 for(
auto& i : *c->p_all_relationships)
556 read_relationships->push_back(i);
559 else if( __builtin_expect((c !=
nullptr), 1) ) {
560 if( __builtin_expect((re_read ==
true), 0) ) {
561 OksData *d_end =
data + c->number_of_all_attributes() + c->number_of_all_relationships();
597 bool attr_is_closed(
false);
603 bool name_was_read(
false);
613 attr_is_closed =
true;
619 name_was_read =
true;
620 if( __builtin_expect((c !=
nullptr), 1) ) {
622 info_i = c->p_data_info->find(i_name);
623 if( __builtin_expect((info_i == c->p_data_info->end() || info_i->second->attribute ==
nullptr), 0) ) {
624 if(non_silent_mode) {
625 std::string msg = std::string(
"Read object \"") +
GetId() +
'@' + c->get_name() +
'\"';
627 Oks::warning_msg(msg.c_str()) <<
" skip attribute \"" << attr.
value() <<
"\", which is not defined in the schema\n";
631 info = info_i->second;
640 attr.
value()[0] != 0 &&
643 (attr.
value()[0] !=
'-')
651 num =
static_cast<int32_t
>(strtol(attr.
value(), &__sanity, 0));
662 if( __builtin_expect((!name_was_read), 0) ) {
672 catch (std::exception & e) {
677 if( __builtin_expect((a !=
nullptr), 1) ) {
681 if( __builtin_expect((check_re_read), 0) ) {
683 read_attributes->remove(a);
705 if(read_params.
format !=
'n')
706 d2.
read(read_params, &a2);
710 if(non_silent_mode) {
715 if(read_params.
format !=
'n')
716 dx->
read(read_params, a);
725 if(read_params.
format !=
'n')
726 d2.
read(read_params, &a2, num);
729 if(attr_is_closed ==
false)
730 d2.
read(&a2, read_params);
735 if(non_silent_mode) {
740 if(read_params.
format !=
'n')
741 dx->
read(read_params, a, num);
744 if(attr_is_closed ==
false)
745 dx->
read(a, read_params);
759 catch (std::exception & e) {
764 if( __builtin_expect((check_re_read), 0) ) {
777 if(read_params.
format !=
'n')
781 if(read_params.
format !=
'n')
782 OksData(read_params, &a2, num);
790 catch (std::exception & e) {
798 if(read_params.
format !=
'n')
803 std::string s(
"\'/attr\' is expected instead of \'");
806 throw std::runtime_error( s.c_str() );
812 catch (std::exception & e) {
839 if( __builtin_expect((c !=
nullptr), 1) ) {
841 info_i = c->p_data_info->find(i_name);
842 if( __builtin_expect((info_i == c->p_data_info->end() || info_i->second->relationship ==
nullptr), 0) ) {
843 if(non_silent_mode) {
844 std::string msg = std::string(
"Read object \"") +
GetId() +
'@' + c->get_name() +
'\"';
846 Oks::warning_msg(msg.c_str()) <<
" skip relationship \"" << attr.
value() <<
"\", which is not defined in the schema\n";
850 info = info_i->second;
856 else if(read_params.
format ==
'n') {
859 if( __builtin_expect((value.
m_class ==
nullptr && attr.
value_len() > 0), 0) ) {
871 num =
static_cast<int32_t
>(strtol(attr.
value(), &__sanity, 0));
883 catch (std::exception & e) {
892 if( __builtin_expect((r !=
nullptr), 1) ) {
898 if( __builtin_expect((check_re_read), 0) ) {
900 read_relationships->remove(r);
912 if(read_params.
format ==
'n')
913 d2.
read(&dummy, value);
915 d2.
read(read_params, &dummy);
919 if(read_params.
format ==
'n')
922 dx->
read(read_params, r);
930 if(read_params.
format ==
'n')
931 d2.
read(&dummy, read_params);
933 d2.
read(read_params, &dummy, num);
937 if(read_params.
format ==
'n')
938 dx->
read(r, read_params);
940 dx->
read(read_params, r, num);
947 catch (std::exception & e) {
964 if(read_params.
format !=
'n')
968 if(read_params.
format ==
'n')
977 catch (std::exception & e) {
985 if(read_params.
format !=
'n')
990 std::string s(
"\'/rel\' is expected instead of \'");
993 throw std::runtime_error( s.c_str() );
999 catch (std::exception & e) {
1008 throw oks::FailedRead(std::string(
"object \"") +
uid.object_id +
'@' + c->get_name() +
'\"', e);
1010 catch (std::exception & e) {
1017 if( __builtin_expect((check_re_read), 0) ) {
1018 if(read_attributes) {
1019 if(!read_attributes->empty()) {
1020 for(
auto i = read_attributes->begin(); i != read_attributes->end(); i = read_attributes->erase(i)) {
1021 OksData d = (*i)->p_init_data;
1030 throw oks::ObjectInitError(
this, std::string(
"cannot reset default value of attribute \"") + (*i)->get_name() +
'\"', ex);
1035 delete read_attributes;
1038 if(read_relationships) {
1039 if(!read_relationships->empty()) {
1040 for(
auto i = read_relationships->begin(); i != read_relationships->end(); i = read_relationships->erase(i)) {
1044 if(d2 && *d2 != d) {
1050 throw oks::ObjectInitError(
this, std::string(
"cannot reset value of relationship \"") + (*i)->get_name() +
'\"', ex);
1055 delete read_relationships;
1063 throw std::runtime_error(
1064 " ***** Can't read objects of undefined class *****\n"
1065 " ***** from file saved in non-extended format. *****\n"
1066 " ***** Fix the problem first. Processing terminated. *****\n"
1070 if(c->p_all_attributes) {
1071 for(
const auto& i : *c->p_all_attributes) {
1075 if(i->get_is_multi_values()) {
1076 d.read(read_params, i,
__get_num(read_params));
1079 d.read(read_params, i);
1082 if(d !=
data[count]) {
1088 if(i->get_is_multi_values()) {
1100 if(c->p_all_relationships) {
1101 for(
const auto& i : *c->p_all_relationships) {
1106 d.read(read_params, i,
__get_num(read_params));
1109 d.read(read_params, i);
1112 if(d !=
data[count]) {
1136 std::ostringstream s;
1137 s <<
"Failed to read obj close tag (\'/" << read_params.
object_tag <<
"\' is expected)";
1138 throw std::runtime_error( s.str().c_str() );
1144 catch (std::exception & e) {
1179 if(!c->p_kernel->get_active_data()) {
1180 Oks::error_msg(
"OksObject::OksObject(const OksClass*, const char *)") <<
" Can not create new object since there is no active data file\n";
1185 uid.object_id = (object_id ? object_id :
"");
1191 uid.class_id =
nullptr;
1205 if(!parentObj.
uid.class_id->p_kernel->get_active_data()) {
1206 Oks::error_msg(
"OksObject::OksObject(const OksObject&, const char *)") <<
" Can not create new object since there is no active data file\n";
1212 uid.object_id = (object_id ? object_id :
"");
1218 uid.class_id =
nullptr;
1223 int count = c->p_instance_size;
1224 int num_of_attr = c->p_all_attributes->size();
1227 while(j < num_of_attr) {
1233 std::list<OksRelationship *>::iterator i = c->p_all_relationships->begin();
1237 const char * relationshipName = r->get_name().c_str();
1267 uid.class_id =
nullptr;
1278 uid.class_id =
nullptr;
1280 memcpy(
static_cast<void *
>(&
data[
offset]),
static_cast<const void *
>(d),
sizeof(
OksData));
1284 data (new
OksData[c->p_instance_size]),
1285 p_user_data (user_data),
1286 p_int32_id (int32_id),
1287 p_duplicated_object_id_idx (duplicated_object_id_idx),
1295 if(
size_t data_size = c->p_instance_size *
sizeof(
OksData*)) {
1296 bzero(data, data_size);
1303 if(!o->
uid.class_id || fast) {
1310 std::unique_ptr<std::ostringstream> error_text;
1314 for(OksClass::Map::const_iterator i = classes.begin(); i != classes.end(); ++i) {
1316 if(c->p_all_relationships ==
nullptr || c->p_all_relationships->empty())
continue;
1319 for(OksObject::Map::const_iterator j = objects->begin(); j != objects->end(); ++j) {
1320 size_t offset = c->number_of_all_attributes();
1321 for(std::list<OksRelationship *>::iterator k = c->p_all_relationships->begin(); k != c->p_all_relationships->end(); ++k, ++
offset) {
1329 for(
const auto& l : *d->data.LIST) {
1338 if(!error_text.get()) {
1339 error_text.reset(
new std::ostringstream());
1340 *error_text <<
"since it is referenced by:";
1342 *error_text <<
"\n * object " << ref <<
" via relationship \"" << (*k)->get_name() <<
'\"';
1349 if(error_text.get()) {
1380 static std::mutex s_mutex;
1381 static std::set<OksObject *, std::less<OksObject *> > oset;
1385 std::lock_guard lock(s_mutex);
1392 if(c->p_all_relationships && !c->p_all_relationships->empty()) {
1393 OksData *di =
data + c->number_of_all_attributes();
1395 for(std::list<OksRelationship *>::iterator i = c->p_all_relationships->begin(); i != c->p_all_relationships->end(); ++i, ++di) {
1398 if(r->get_is_composite() ==
false || k->
p_close_all ==
true)
continue;
1408 bool delete_obj(r->get_is_dependent() && !o->
p_rcr);
1411 std::lock_guard lock(s_mutex);
1412 delete_obj = (oset.find(o) == oset.end());
1417 d->data.OBJECT =
nullptr;
1422 for(
const auto& i2 : *d->data.LIST) {
1429 bool delete_obj(r->get_is_dependent() && !o->
p_rcr);
1432 std::lock_guard lock(s_mutex);
1433 delete_obj = (oset.find(o) == oset.end());
1438 i2->
data.OBJECT =
nullptr;
1448 for(
const auto& i : *c->p_indices)
1449 i.second->remove_obj(
this);
1452 int count = c->p_instance_size;
1468 for(std::list<OksRCR *>::const_iterator i =
p_rcr->begin(); i !=
p_rcr->end(); ++i) {
1476 std::lock_guard lock(s_mutex);
1508 if(new_id ==
uid.object_id)
return;
1513 catch(std::exception& ex) {
1519 if(c->get_object(new_id)) {
1526 std::set<OksFile *> updated_files;
1527 std::list<OksObject *> updated_objects;
1529 updated_files.insert(
file);
1530 updated_objects.push_back(
this);
1534 for(OksClass::Map::const_iterator i = classes.begin(); i != classes.end(); ++i) {
1537 size_t d_end = c->p_instance_size;
1538 size_t d_begin = c->p_all_attributes->size();
1539 if(objs && (d_end != d_begin)) {
1540 for(OksObject::Map::const_iterator j = objs->begin(); j != objs->end(); ++j) {
1545 for(
size_t k = d_begin; k != d_end && o; ++k) {
1546 const OksData & d = o->data[k];
1548 updated_objects.push_back(o);
1549 updated_files.insert(o->file);
1554 for(OksData::List::const_iterator l = list.begin(); l != list.end(); ++l) {
1557 updated_objects.push_back(o);
1558 updated_files.insert(o->file);
1571 for(std::set<OksFile *>::const_iterator i = updated_files.begin(); i != updated_files.end(); ++i) {
1581 uid.object_id = new_id;
1588 for(std::set<OksFile *>::const_iterator i = updated_files.begin(); i != updated_files.end(); ++i) {
1589 (*i)->set_updated();
1593 for(std::list<OksObject *>::const_iterator i = updated_objects.begin(); i != updated_objects.end(); ++i) {
1594 (*i)->change_notify();
1605 if (o1 ==
nullptr || o2 ==
nullptr)
1608 return (o1->
uid.class_id->get_name() == o2->
uid.class_id->get_name() && o1->
uid.object_id == o2->
uid.object_id);
1621 while (count < uid.class_id->p_instance_size)
1656 s <<
"Object " << &o << std::endl;
1664 const std::list<OksAttribute *> * alist = c->all_attributes();
1666 if(alist && !alist->empty()) {
1667 s <<
" Attributes are:\n";
1669 for(std::list<OksAttribute *>::const_iterator i = alist->begin(); i != alist->end(); ++i) {
1671 s.setf(((*i)->get_format() ==
OksAttribute::Hex ? std::ios::hex : std::ios::oct), std::ios::basefield);
1672 s.setf(std::ios::showbase);
1675 s <<
" " << (*i)->get_name() <<
": " << *di++ << std::endl;
1678 s.setf(std::ios::dec, std::ios::basefield);
1679 s.unsetf(std::ios::showbase);
1684 s <<
" There are no attributes\n";
1691 const std::list<OksRelationship *> * rlist = c->all_relationships();
1693 if(rlist && !rlist->empty()) {
1694 s <<
" Relationships are:\n";
1696 for(std::list<OksRelationship *>::const_iterator i = rlist->begin(); i != rlist->end(); ++i)
1697 s <<
" " << (*i)->get_name() <<
": " << *di++ << std::endl;
1700 s <<
" There are no relationships\n";
1717 if (d.data.OBJECT && kernel.
is_dangling(d.data.OBJECT))
1719 d.data.OBJECT =
nullptr;
1722 return (d.data.OBJECT !=
nullptr);
1728 for (OksData::List::iterator i = d.data.LIST->begin(); i != d.data.LIST->end();)
1735 i = d.data.LIST->erase(i);
1743 return (!d.data.LIST->empty());
1756 const std::string * class_name =
nullptr;
1757 const std::string * object_id =
nullptr;
1761 class_name = &d.data.OBJECT->GetClass()->get_name();
1762 object_id = &d.data.OBJECT->GetId();
1766 class_name = &d.data.UID.class_id->get_name();
1767 object_id = d.data.UID.object_id;
1771 class_name = d.data.UID2.class_id;
1772 object_id = d.data.UID2.object_id;
1799 for (
const auto& a : *alist)
1804 if (force_defaults || d != a->p_init_data || a->p_data_type ==
OksData::date_type || a->p_data_type ==
OksData::time_type || (a->get_init_value().empty() ==
false && (a->get_is_multi_values() ==
true || a->is_number() ==
false || a->get_init_value().size() > 1 || a->get_init_value()[0] !=
'0')))
1817 if (a->get_is_multi_values() ==
false)
1824 if (d.data.LIST->empty())
1835 for (
const auto& x : *d.data.LIST)
1851 xmls.
get_stream().setf(std::ios::dec, std::ios::basefield);
1852 xmls.
get_stream().unsetf(std::ios::showbase);
1860 for (
const auto& r : *rlist)
1882 for (
const auto& x : *rel_data.
data.
LIST)
1904 catch (std::ios_base::failure & ex)
1908 catch (std::exception & ex)
1921 OksDataInfo::Map::const_iterator i =
uid.class_id->p_data_info->find(name);
1923 if(i ==
uid.class_id->p_data_info->end()) {
1924 std::ostringstream text;
1925 text <<
"object " <<
this <<
" has no attribute \"" << name <<
'\"';
1941 if(
uid.class_id->get_kernel()->get_silence_mode() ==
false) {
1942 Oks::warning_msg(
"OksObject::SetAttributeValue(const OksDataInfo *, OksData *)")
1943 <<
" * ODI attribute name: \'" << a->
get_name() <<
"\'\n"
1944 " * ODI data offset: \'" <<
offset <<
"\'\n"
1945 " * OKS data (new): \'" << *d <<
"\' type: " << (int)d->type <<
"\n"
1947 " Object " <<
this <<
":\n"
1948 " Convert attribute \"" << a->
get_name() <<
"\" value since the OksData::type is invalid\n";
1973 if(
uid.class_id->p_indices) {
1974 OksIndex::Map::iterator j =
uid.class_id->p_indices->find(a);
1975 if(j !=
uid.class_id->p_indices->end()) {
1982 if(i) i->insert(
this);
1992 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
1994 if(i ==
uid.class_id->p_data_info->end()) {
1995 std::ostringstream text;
1996 text <<
"object " <<
this <<
" has no attribute \"" << name <<
'\"';
2006 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2008 if(i ==
uid.class_id->p_data_info->end()) {
2009 std::ostringstream text;
2010 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2023 this,
true, r->get_name(),
2024 "set to (null) is not allowed since the relationship has non-zero low cardinality constraint"
2033 if(!class_type)
return;
2035 const OksClass * rel_class_type = r->p_class_type;
2037 if(class_type != rel_class_type) {
2040 if(super_classes && !super_classes->empty()) {
2041 for(
const auto& i : *super_classes) {
2042 if(rel_class_type == i)
return;
2046 std::ostringstream text;
2047 text <<
"set to an object of class \"" << class_type->get_name() <<
"\" is not allowed since the relationship's class type is \""
2048 << r->get_type() <<
"\" and the class \"" << class_type->get_name() <<
"\" has no such superclass";
2064 std::ostringstream text;
2066 <<
"offset: " <<
offset <<
"; new: \'" << *d <<
"\'; old:" <<
data[
offset] <<
'\'';
2079 if(add_obj != rm_obj) {
2080 if(add_obj) added_objs.insert(add_obj);
2081 if(rm_obj) removed_objs.insert(rm_obj);
2087 if(skip_non_null_check ==
false)
check_non_null(r, d->data.OBJECT);
2091 if(d->data.LIST->empty()) {
2094 this,
true, r->get_name(),
2095 "set to empty list is not allowed since the relationship has non-zero low cardinality constraint"
2100 for(
const auto& i : *d->data.LIST) {
2116 added_objs.insert(o2);
2123 this,
true, r->get_name(),
2124 "the OKS data type is invalid (must be a list of objects or an object)"
2136 removed_objs.insert(i->data.OBJECT);
2144 for(
const auto& i : removed_objs) {
2145 if(added_objs.find(i) == added_objs.end()) {
2146 TLOG_DEBUG(4) <<
"object " << i <<
" was removed from relationship";
2147 i->remove_RCR(
this, r);
2154 for(OksObject::FSet::const_iterator i = added_objs.begin(); i != added_objs.end(); ++i) {
2156 if(removed_objs.find(add_obj) == removed_objs.end()) {
2157 TLOG_DEBUG(4) <<
"object " << add_obj <<
" was added to relationship";
2165 for(OksObject::FSet::const_iterator j = added_objs.begin(); j != i; ++j) {
2166 if(removed_objs.find(*j) == removed_objs.end()) {
2167 (*j)->remove_RCR(
this, r);
2171 for(OksObject::FSet::const_iterator j = removed_objs.begin(); j != removed_objs.end(); ++j) {
2172 if(added_objs.find(*j) == added_objs.end()) {
2191 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2193 if(i ==
uid.class_id->p_data_info->end()) {
2194 std::ostringstream text;
2195 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2210 std::ostringstream text;
2211 text <<
"cannot set value " <<
object <<
" since the relationship has \'many\' high cardinality constraint";
2225 d.data.OBJECT->remove_RCR(
this, r);
2230 object->add_RCR(
this, r);
2235 try { d.data.OBJECT->add_RCR(
this, r); }
catch(
oks::exception& ex2) { ; }
2249 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2251 if(i ==
uid.class_id->p_data_info->end()) {
2252 std::ostringstream text;
2253 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2266 return ((d2->
data.
OBJECT == d->data.OBJECT) ?
true :
false);
2268 const std::string& object_id =
2270 d->type ==
OksData::uid2_type ? *(
static_cast<std::string*
>(d->data.UID2.object_id)) :
2271 *(
static_cast<std::string*
>(d->data.UID.object_id));
2273 const std::string& object_id2 =
2276 *(
static_cast<std::string*
>(d2->
data.
UID.object_id));
2278 if(object_id != object_id2)
return false;
2290 if(pclass_id && pclass_id2)
return (pclass_id == pclass_id2 ?
true :
false);
2292 const std::string& class_id =
2293 (pclass_id ? pclass_id->
get_name() : *(
static_cast<std::string*
>(d->data.UID2.class_id)));
2295 const std::string& class_id2 =
2296 (pclass_id2 ? pclass_id2->
get_name() : *(
static_cast<std::string*
>(d2->
data.
UID2.class_id)));
2298 return (class_id == class_id2 ?
true :
false);
2315 std::ostringstream text;
2316 text <<
"cannot add value " <<
object <<
" since the relationship has no \'many\' high cardinality constraint";
2321 object->add_RCR(
this, r);
2338 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2340 if(i ==
uid.class_id->p_data_info->end()) {
2341 std::ostringstream text;
2342 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2360 std::ostringstream text;
2361 text <<
"cannot remove object " <<
object <<
" since the relationship has no \'many\' high cardinality constraint";
2369 for(OksData::List::iterator i = list->begin(); i != list->end();) {
2373 object->remove_RCR(
this, r);
2382 std::ostringstream text;
2383 text <<
"cannot remove object " <<
object <<
" since the relationship\'s value has no such object";
2391 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2393 if(i ==
uid.class_id->p_data_info->end()) {
2394 std::ostringstream text;
2395 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2405 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2407 if(i ==
uid.class_id->p_data_info->end()) {
2408 std::ostringstream text;
2409 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2419 if(object_id.empty() || class_id.empty()) {
2434 OksClass *c =
uid.class_id->p_kernel->find_class(class_id);
2439 else if(r->get_type() != class_id) {
2440 std::ostringstream text;
2441 text <<
"cannot set value \"" << object_id <<
'@' << class_id <<
"\" since the class \"" << class_id
2442 <<
"\" is not defined and it is impossible to check its validity for given type of relationship";
2447 std::ostringstream text;
2448 text <<
"cannot set object \"" << object_id <<
'@' << class_id <<
"\" since the relationship has \'many\' high cardinality constraint";
2454 if(c) o = c->get_object(object_id);
2476 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2478 if(i ==
uid.class_id->p_data_info->end()) {
2479 std::ostringstream text;
2480 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2487 if(class_id.empty() || object_id.empty()) {
2491 const std::string& r_class_type = r->get_type();
2494 OksClass *c =
uid.class_id->p_kernel->find_class(class_id);
2499 else if(r_class_type != class_id) {
2500 std::ostringstream text;
2501 text <<
"cannot add value \"" << object_id <<
'@' << class_id <<
"\" since the class \"" << class_id
2502 <<
"\" is not defined and it is impossible to check its validity for given type of relationship";
2507 std::ostringstream text;
2508 text <<
"cannot add object \"" << object_id <<
'@' << class_id <<
"\" since the relationship has no \'many\' high cardinality constraint";
2514 if(c) o = c->get_object(object_id);
2530 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2532 if(i ==
uid.class_id->p_data_info->end()) {
2533 std::ostringstream text;
2534 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2541 if(object_id.empty() || class_id.empty()) {
2546 std::ostringstream text;
2547 text <<
"cannot remove object \"" << object_id <<
'@' << class_id <<
"\" since the relationship has no \'many\' high cardinality constraint";
2552 OksData d(class_id, object_id);
2555 for(OksData::List::iterator j = list->begin(); j != list->end();) {
2567 std::ostringstream text;
2568 text <<
"cannot remove object \"" << object_id <<
'@' << class_id <<
"\" since the relationship\'s value has no such object";
2576 if(r->get_is_composite() ==
false)
return;
2578 TLOG_DEBUG(4) <<
"object " <<
this <<
" adds RCR to object " << o <<
" throught relationship \"" << r->get_name() <<
'\"';
2581 p_rcr =
new std::list<OksRCR *>();
2584 for(
const auto& i : *
p_rcr) {
2585 if(i->relationship == r) {
2587 TLOG_DEBUG(4) <<
"[this=" <<
this <<
", o=" << o <<
", r=\"" << r->get_name() <<
"\"]: such RCR was already set.";
2590 else if(r->get_is_exclusive()) {
2604 TLOG_DEBUG(4) <<
"object " <<
this <<
" removes RCR from object " << o <<
" through " << r->get_name();
2606 if(r->get_is_composite() ==
false || !p_rcr)
return;
2608 for(std::list<OksRCR *>::iterator i = p_rcr->begin(); i != p_rcr->end(); ++i) {
2618 if(p_rcr->empty()) {
2632 if(d->data.UID.class_id && !d->data.UID.object_id->empty()) {
2633 c = d->data.UID.class_id;
2634 o = c->get_object(d->data.UID.object_id);
2642 if(d->data.UID2.class_id->empty() || d->data.UID2.object_id->empty()) {
2647 c = info.k->find_class(*d->data.UID2.class_id);
2650 o = c->get_object(d->data.UID2.object_id);
2653 std::ostringstream text;
2654 text <<
"Class of object " << *d <<
" is not defined";
2659 if(c != info.r->p_class_type) {
2661 for(OksClass::FList::const_iterator i = slist->begin(); i != slist->end(); ++i) {
2662 if(info.r->p_class_type == *i) {
2669 std::ostringstream text;
2670 text <<
"The relationship has class type \"" << info.r->get_type() <<
"\" and the referenced object " << *d <<
" is not of that class or derived one";
2678 std::ostringstream text;
2679 text <<
"Cannot find object " << *d;
2688 std::ostringstream text;
2689 text <<
"Failed to set relationship value " << o;
2704 std::ostringstream&
add();
2711 else {
p_warnings =
new std::ostringstream();}
2720 add() <<
" * object " << d <<
" via relationship \"" << r->get_name() <<
'\"';
2726 add() <<
" * relationship \"" << r->get_name() <<
"\" has non-zero low cardinality constraint, but it is empty";
2735 if(c->p_all_relationships->empty())
return;
2738 info.k = c->p_kernel;
2741 OksData * d(
data + c->number_of_all_attributes());
2745 for (
auto & i : (*c->p_all_relationships))
2751 if (i->get_low_cardinality_constraint() ==
OksRelationship::One && d->data.OBJECT ==
nullptr) { warnings.
add(i); }
2755 if (d->data.UID.object_id ==
nullptr)
2772 if (d->data.LIST->empty())
2778 for (
const auto& i2 : *d->data.LIST)
2797 if (i->get_low_cardinality_constraint() ==
OksRelationship::One && d->data.UID2.object_id ==
nullptr) { warnings.
add(i); }
2814 std::ostringstream text;
2817 text <<
"There " << s1 <<
" " << warnings.
p_warnings_count <<
" unresolved reference" << s2 <<
" from object " <<
this
2827 const size_t num_of_attrs (
uid.class_id->number_of_all_attributes());
2828 const size_t num_of_rels (
uid.class_id->number_of_all_relationships());
2832 for(
size_t i = 0; i < num_of_rels; ++i) {
2839 if(o && o->
file == f) {
2841 std::cout <<
"- unbind_file(\'" << f->get_full_file_name() <<
"\') in " <<
this <<
": replace " << *d;
2845 if(verbose) std::cout <<
" by " << *d << std::endl;
2849 for(
const auto& j : *d->data.LIST) {
2853 if(o && o->
file == f) {
2855 std::cout <<
"+ unbind_file(\'" << f->get_full_file_name() <<
"\') in " <<
this <<
": replace " << *j;
2859 if(verbose) std::cout <<
" by " << *j << std::endl;
2871 return uid.class_id->p_kernel->p_change_object_notify_fn;
2919 if(includes.find(o2->
get_file()) == includes.end()) {
2920 if(
GetClass()->get_kernel()->get_silence_mode() ==
false) {
2922 msg <<
": no files inclusion path between referenced objects:\n"
2927 for(std::set<OksFile *>::const_iterator j = includes.begin(); j != includes.end(); ++j) {
2928 std::cerr <<
" * \'" << (*j)->get_full_file_name() <<
"\'\n";
2944 std::ostringstream text;
2946 if(result.empty()) {
2947 text <<
" * object " << obj <<
" has dangling references:\n";
2950 text <<
" - object " << d <<
" referenced via \'" << r.get_name() <<
"\'\n";
2952 result += text.str();
2971 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
2995 bool return_value =
true;
3007 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
3016 if(d->IsConsistent(odi.
relationship,
this,
"ERROR") ==
false) {
3017 return_value =
false;
3027 if(
GetClass()->get_kernel()->get_silence_mode() ==
false) {
3029 "ERROR: the schema file is not included for object " <<
this <<
".\n"
3031 " cannot be loaded or edited without inclusion of additional files.\n"
3032 " The file shall explicitly or implicitly (i.e. via other included files) include schema file\n"
3040 return return_value;
3055static void _references(
const OksObject * obj,
unsigned long recursion_depth, RefData& data);
3063 std::pair<OksObject::FSet::iterator,bool> ret = data.tested_objs.insert(
const_cast<OksObject *
>(o));
3065 if(ret.second==
true) {
3066 if(data.classes ==
nullptr || data.classes->find(
const_cast<OksClass *
>(o->
GetClass())) != data.classes->end()) {
3067 data.refs.insert(
const_cast<OksObject *
>(o));
3081 if(recursion_depth == 0)
return;
3083 size_t l1 = obj->GetClass()->number_of_all_attributes();
3084 size_t l2 = l1 + obj->GetClass()->number_of_all_relationships();
3088 OksData * d(obj->GetRelationshipValue(&odi));
3096 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
3114 std::lock_guard lock(
uid.class_id->p_kernel->p_objects_refs_mutex);
3124 TLOG_DEBUG(2) <<
"OksObject::references(" <<
this <<
", " << recursion_depth <<
") returns " << refs.size() <<
" objects";
3131 bool any_name = (name ==
"*");
3137 for(OksClass::Map::const_iterator i = all_classes.begin(); i != all_classes.end(); ++i) {
3139 if(any_name || c->find_relationship(name) !=
nullptr) {
3141 for(OksObject::Map::const_iterator j = objs->begin(); j != objs->end(); ++j) {
3143 unsigned short l1, l2;
3146 l1 = c->number_of_all_attributes();
3147 l2 = l1 + c->number_of_all_relationships();
3150 l1 = c->data_info(name)->offset;
3159 if(
this == d->data.OBJECT) {
3161 result->push_back(o);
3167 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
3172 result->push_back(o);
static std::string fill(const OksObject *obj, const std::string &name, const OksObject *p1, const OksObject *p2)
Failed move item to file.
static std::string fill(const OksObject *o, const std::string &reason)
static std::string fill(const OksObject *o, const std::string &reason)
static std::string fill(const OksObject *o, const std::string &what, const std::string &reason)
static std::string fill(const OksObject *o, const std::string &reason)
static std::string fill(const OksObject *o, const std::string &reason)
std::string fill(const OksObject *obj, const OksRelationship *rel, const std::string &why, const std::string &reason)
const OksRelationship * p_rel
static std::string fill(const OksObject *obj, bool is_rel, const std::string &name, const std::string &reason)
static std::string fill(const OksObject *obj, const std::string &why, const std::string &reason)
static std::string fill(const OksObject *obj, bool is_rel, const std::string &name, const std::string &reason)
static const char * s8_int_type
static const char * u32_int_type
static const char * u8_int_type
static const char * time_type
static const char * s64_int_type
bool get_is_multi_values() const noexcept
static const char * bool_type
const std::string & get_type() const noexcept
Get attribute string type.
const std::string & get_name() const noexcept
out stream operator
static const char * class_type
static const char * string_type
static const char * enum_type
static const char * s32_int_type
static const char * s16_int_type
OksData::Type get_data_type() const noexcept
static const char * u64_int_type
static const char * double_type
const std::string & get_init_value() const noexcept
const std::string * get_enum_value(const char *s, size_t length) const
Returns pointer on internal enumerator data equal to given string, if such string is defined in attri...
static const char * u16_int_type
static const char * date_type
static const char * float_type
static OksData::Type get_data_type(const std::string &type) noexcept
Converts string to attribute OKS data type.
const std::list< OksAttribute * > * all_attributes() const noexcept
size_t number_of_all_relationships() const noexcept
OksKernel * get_kernel() const noexcept
const std::string & get_name() const noexcept
size_t number_of_all_attributes() const noexcept
OksFile * get_file() const noexcept
std::list< OksClass *, boost::fast_pool_allocator< OksClass * > > FList
std::map< const char *, OksClass *, SortStr > Map
const std::list< OksRelationship * > * all_relationships() const noexcept
Provides interface to the OKS XML schema and data files.
void lock()
Lock OKS file.
const std::string & get_full_file_name() const
OksObject * remove_obj(OksObject *)
Provides interface to the OKS kernel.
OksObject::notify_obj p_change_object_notify_fn
OksFile * get_active_data() const
Get active OKS data file.
bool is_dangling(OksClass *class_ptr) const
Check pointer on oks class.
static std::mutex p_parallel_out_mutex
bool get_verbose_mode() const
Get status of verbose mode. The method returns true, if the verbose mode is switched 'On'.
bool get_test_duplicated_objects_via_inheritance_mode() const
Get status of test inherited duplicated objects mode. The method returns true, if the mode is switche...
OksObject::notify_obj p_delete_object_notify_fn
bool get_allow_duplicated_objects_mode() const
Get status of duplicated objects mode. The method returns true, if the duplicated objects mode is swi...
const OksClass::Map & classes() const
Get classes.
void * p_delete_object_notify_param
void undefine(OksObject *o)
void * p_change_object_notify_param
OksObject::notify_obj p_create_object_notify_fn
bool get_silence_mode() const
Get status of silence mode. The method returns true, if the silence mode is switched 'On'....
std::shared_mutex p_schema_mutex
void * p_create_object_notify_param
OksObject describes instance of OksClass.
struct dunedaq::oks::OksObject::OksUid uid
static void destroy(OksObject *obj, bool fast=false)
Destroy OKS object.
void AddRelationshipValue(const std::string &name, OksObject *object)
Add object value to multi-value relationship by name.
void RemoveRelationshipValue(const std::string &name, OksObject *object)
Remove object value from multi-value relationship by name.
void __report_type_cvt_warning(const oks::ReadFileParams &, const OksAttribute &, const OksData &, const OksData::Type, int32_t) const
void check_file_lock(const OksAttribute *, const OksRelationship *)
void put(OksXmlOutputStream &, bool force_defaults) const
std::list< OksRCR * > * p_rcr
std::unordered_map< const std::string *, OksObject *, oks::hash_str, oks::equal_str > Map
OksData * GetRelationshipValue(const std::string &) const
Get value of relationship by name.
std::unordered_set< OksObject *, oks::hash_obj_ptr, oks::equal_obj_ptr > FSet
static const char class2_xml_attribute[]
static const char relationship_xml_tag[]
void references(OksObject::FSet &refs, unsigned long recursion_depth, bool add_self=false, oks::ClassSet *classes=0) const
OksFile * get_file() const
void init1(const OksFile *=0)
static const char attribute_xml_tag[]
static const char obj2_xml_tag[]
static void put_object_attributes(OksXmlOutputStream &, const OksData &)
void __report_cardinality_cvt_warning(const oks::ReadFileParams &, const OksRelationship &) const
static const char value_xml_attribute[]
std::string report_dangling_references() const
void SetRelationshipValue(const std::string &name, OksData *data, bool skip_non_null_check=false)
Set value of relationship by name.
void read_body(const oks::ReadFileParams &, bool)
int32_t __get_num(const oks::ReadFileParams ¶ms)
void add_RCR(OksObject *, const OksRelationship *)
void check_class_type(const OksRelationship *, const OksClass *)
static const char id_xml_attribute[]
void set_file(OksFile *file, bool update_owner=true)
Move object to different file.
static const char obj_xml_tag[]
static OksObject * read(const oks::ReadFileParams &)
FList * get_all_rels(const std::string &name="*") const
Return objects referencing this one via relationship with given name.
void * GetTransientData() const
Get transient user data associated with given object. Return data set using SetTransientData() method...
void check_non_null(const OksRelationship *, const OksObject *)
void unbind_file(const OksFile *)
OksObject(const OksClass *oks_class, const char *object_id=0, bool skip_init=false)
OKS object constructor.
static const char id2_xml_attribute[]
static const char num_xml_attribute[]
const OksClass * GetClass() const
static bool are_equal_fast(const OksObject *o1, const OksObject *o2)
The fast equal method.
static const char class_xml_attribute[]
static void bind(OksData *, const BindInfo &)
static const char name_xml_attribute[]
void set_id(const std::string &id)
Set object ID.
void remove_RCR(OksObject *, const OksRelationship *) noexcept
static const char type_xml_attribute[]
notify_obj get_change_notify() const
static const char data_xml_tag[]
void init2(bool skip_init=false)
bool is_consistent(const std::set< OksFile * > &, const char *msg) const
void SetAttributeValue(const std::string &name, OksData *data)
Set value of attribute by name.
bool check_links_and_report(const OksObject *, const std::set< OksFile * > &, const std::string &, const char *) const
void(*) notify_obj(OksObject *, void *)
std::list< OksObject *, boost::fast_pool_allocator< OksObject * > > FList
bool operator==(const OksObject &) const
The equality operator.
void SetTransientData(void *d) const
Set transient user data associated with given object. Such data are not stored on file and only exist...
static const char ref_xml_tag[]
const std::string & GetId() const
int32_t p_duplicated_object_id_idx
OksData * GetAttributeValue(const std::string &name) const
Get value of attribute by name.
@ ObjectNormalConstructor
@ ObjectStreamConstructor
const std::string & get_name() const noexcept
void put_last_tag(const char *, size_t len)
void put_attribute(const char *, size_t len, const char *)
void put_start_tag(const char *, size_t len)
std::ostream & get_stream() const
static std::ostream & warning_msg(const char *)
static std::ostream & error_msg(const char *)
virtual const char * what() const noexcept
#define OSK_PROFILING(FID, K)
#define TLOG_DEBUG(lvl,...)
bool cmp_str1(const char *s1, const char s2[2])
bool cmp_str4(const char *s1, const char s2[5])
bool cmp_str9(const char *s1, const char s2[10])
static void _references(const OksObject *obj, unsigned long recursion_depth, RefData &data)
static void insert2refs(const OksObject *o, unsigned long recursion_depth, RefData &data)
static void test_dangling_references(const OksObject *obj, const OksData &d, const OksRelationship &r, std::string &result)
void validate_not_empty(const std::string &value, const char *name)
std::ostream & operator<<(std::ostream &s, const oks::exception &ex)
std::unordered_set< const OksClass *, oks::hash_class_ptr, oks::equal_class_ptr > ClassSet
bool cmp_str2(const char *s1, const char s2[3])
bool cmp_str5(const char *s1, const char s2[6])
static bool trim_dangling(OksData &d, const OksKernel &kernel)
static void __throw_unknown_type(const oks::ReadFileParams ¶ms, const char *atype)
bool cmp_str3(const char *s1, const char s2[4])
static bool cmp_data(OksData *d, OksData *d2)
Unknown serialization type
#define READ_OBJ_HEADER(F1, S1, F2, S2)
std::ostringstream & add()
std::ostringstream * p_warnings
void add(const OksData &d, const OksRelationship *r)
unsigned int p_warnings_count
Struct OKS data information.
const OksAttribute * attribute
const OksRelationship * relationship
the structure to pass common parameters to various read() methods of OksData and OksObject class
void sort(bool ascending=true)
void SetNullValue(const OksAttribute *a)
void cvt(OksData *to, const OksAttribute *attr) const
Convert data to new type.
union dunedaq::oks::OksData::Data data
std::list< OksData *, boost::fast_pool_allocator< OksData * > > List
void SetValue(const char *s, const OksAttribute *a)
void read(const oks::ReadFileParams &, const OksAttribute *, int32_t)
private methods which can be used by OksObject class only
void SetValues(const char *, const OksAttribute *a)
enum dunedaq::oks::OksData::Type type
void ConvertTo(OksData *, const OksRelationship *) const
void check_range(const OksAttribute *a) const
Check range of data.
void set_init_value(const OksAttribute *attr, bool skip_init)
Set value defined by initial value of attribute.
The struct OksRCR describes Reverse Composite Relationship (i.e. back reference from child to composi...
const OksRelationship * relationship
ReloadObjects * reload_objects
OksObject::FSet tested_objs
RefData(OksObject::FSet &r, oks::ClassSet *cs)
OksObject * pop(const OksClass *c, const std::string &id)
std::vector< OksObject * > created
struct dunedaq::oks::OksData::Data::@165 UID
struct dunedaq::oks::OksData::Data::@166 UID2
const std::string * ENUMERATION