61 s <<
"Failed to read \'" <<
what <<
"\' of object " << o <<
'\n' << reason;
69 s <<
"Failed to create object " << o <<
'\n' << reason;
77 s <<
"Failed to save object " << o <<
'\n' << reason;
85 s <<
"Failed to rename object " << o <<
'\n' << reason;
93 s <<
"Failed to destroy object " << o <<
'\n' << reason;
100 std::ostringstream s;
101 s <<
"Failed to set " << (is_rel ?
"relationship" :
"attribute") <<
" \'" << name <<
"\' of object " <<
obj <<
'\n' << reason;
108 std::ostringstream s;
109 s <<
"Failed to get " << (is_rel ?
"relationship" :
"attribute") <<
" \'" << name <<
"\' of object " <<
obj <<
'\n' << reason;
116 std::ostringstream s;
117 s <<
"Object " <<
obj <<
" cannot be linked with " << p1 <<
" via exclusive relationship \'" << name <<
"\' since it is already referenced by object " << p2;
124 std::ostringstream s;
125 s <<
"Failed to init object " <<
obj <<
" because " << why <<
'\n' << reason;
133 std::ostringstream s;
134 s <<
"Failed to bind relationship";
135 if(
p_rel) { s <<
" \"" <<
p_rel->get_name() <<
'\"'; }
else { s <<
's'; }
136 s <<
" of object " <<
obj <<
" because:\n" << why;
137 if(!reason.empty()) s <<
'\n' << reason;
150 std::lock_guard lock(
uid.class_id->p_unique_id_mutex);
154 for (
unsigned long i = 0; i < 0xFFFFFFFF; ++i)
156 sprintf(unique_id.get(),
"%s^%lu",
uid.object_id.c_str(), i);
157 std::string id(unique_id.get());
158 if(
uid.class_id->get_object(
id) ==
nullptr)
169 if (std::vector<OksClass *> * cs =
uid.class_id->p_inheritance_hierarchy)
171 for (std::vector<OksClass *>::const_iterator j = cs->begin(); j != cs->end(); ++j)
174 if (__builtin_expect((o !=
nullptr), 0))
178 "has ID equal with \'" <<
uid.object_id <<
'@' <<
uid.class_id->get_name() <<
"\' object and their classes belong to the same inheritance hierarchy "
179 "(the OKS kernel is configured in the \"test-duplicated-objects-within-inheritance-hierarchy\" mode for compatibility with config and DAL tools)";
190 const std::string & object_id =
uid.object_id;
191 const OksKernel * kernel(c->get_kernel());
196 if( __builtin_expect((c->get_is_abstract()), 0) ) {
197 std::ostringstream text;
198 text <<
"the class \'" << c->get_name() <<
"\' is abstract";
205 if( __builtin_expect((!object_id.empty()), 1) ) {
210 OksObject * o = c->get_object(object_id);
212 if( __builtin_expect((o !=
nullptr), 0) ) {
217 <<
"WARNING [OksObject constructor]:\n"
218 " Cannot create object " << o;
224 " Skip above problem since OKS kernel is configured in \'ignore-duplicated-objects\' mode\n"
225 <<
" Create duplicated object with ID = \'" <<
uid.object_id <<
"\'\n";
285 if (c->p_all_attributes)
287 if (skip_init ==
false)
289 for (
const auto& i : *c->p_all_attributes)
290 data[count++] = i->p_init_data;
294 for (
const auto& i : *c->p_all_attributes)
295 data[count++] = i->p_empty_init_data;
299 if(c->p_all_relationships) {
300 for(
const auto& i : *c->p_all_relationships) {
304 d.data.OBJECT =
nullptr;
317 if( __builtin_expect((c->p_indices !=
nullptr), 0) ) {
318 for(
auto& i : *c->p_indices) i.second->insert(
this);
322 c->p_kernel->define(
this);
332#define READ_OBJ_HEADER(F1, S1, F2, S2) \
334 OksXmlAttribute attr(read_params.s); \
335 if(oks::cmp_str1(attr.name(), ">") || oks::cmp_str1(attr.name(), "/")) { break; } \
336 else if(F1(attr.name(), S1)) { \
337 std::shared_lock lock(read_params.oks_kernel->p_schema_mutex); \
338 c = read_params.oks_kernel->find_class(attr.value()); \
339 if( __builtin_expect((c == nullptr), 0) ) { \
340 std::ostringstream text; \
341 text << "cannot find class \"" << attr.value() << "\" (line " \
342 << read_params.s.get_line_no() << ", char " \
343 << read_params.s.get_line_pos() << ')'; \
344 throw std::runtime_error( text.str().c_str() ); \
347 else if(F2(attr.name(), S2)) id.assign(attr.value(), attr.value_len()); \
349 read_params.s.throw_unexpected_attribute(attr.name()); \
385 catch (std::exception & e) {
397 if(read_params.
format !=
'c') {
407 catch (std::exception & e) {
418 catch(std::exception& ex) {
424 o->read_body(read_params,
true);
432 if(c ==
nullptr &&
id.empty()) {
return nullptr; }
444 obj->create_notify();
447 TLOG_DEBUG(3) <<
"*** create object " <<
obj <<
" while reload data ***";
458 const char * type_str;
477 default: type_str =
"unknown";
484 " convert value from wrong type \"" << (num == -1 ?
"single" :
"multi") <<
"-value " << type_str <<
"\" to \"" << (a.
get_is_multi_values() ?
"multi" :
"single")
485 <<
"-value " << a.
get_type() <<
"\" as required for attribute \"" << a.
get_name() <<
"\"\n"
486 <<
" converted value: " << d << std::endl;
495 " mismatch between relationship \"" << r.get_name() <<
"\" cardinality and its value (save data file with new schema)." << std::endl;
501 std::ostringstream s;
502 s <<
"Unknown attribute type \"" << atype <<
'\"';
511 int32_t num =
static_cast<int32_t
>(strtol(params.
s.
m_cvt_char->
m_buf, &__sanity, 0));
526 bool was_updated =
false;
534 file = read_params.
f;
541 if( __builtin_expect((read_params.
format !=
'c'), 1) ) {
542 OksDataInfo::Map::iterator info_i;
548 std::list<const OksAttribute *> * read_attributes =
nullptr;
549 std::list<const OksRelationship *> * read_relationships =
nullptr;
551 if( __builtin_expect((check_re_read), 0) ) {
552 if(c->p_all_attributes && !c->p_all_attributes->empty()) {
553 read_attributes =
new std::list<const OksAttribute *>();
554 for(
auto& i : *c->p_all_attributes)
555 read_attributes->push_back(i);
558 if(c->p_all_relationships && !c->p_all_relationships->empty()) {
559 read_relationships =
new std::list<const OksRelationship *>();
560 for(
auto& i : *c->p_all_relationships)
561 read_relationships->push_back(i);
564 else if( __builtin_expect((c !=
nullptr), 1) ) {
565 if( __builtin_expect((re_read ==
true), 0) ) {
566 OksData *d_end =
data + c->number_of_all_attributes() + c->number_of_all_relationships();
602 bool attr_is_closed(
false);
608 bool name_was_read(
false);
618 attr_is_closed =
true;
624 name_was_read =
true;
625 if( __builtin_expect((c !=
nullptr), 1) ) {
627 info_i = c->p_data_info->find(i_name);
628 if( __builtin_expect((info_i == c->p_data_info->end() || info_i->second->attribute ==
nullptr), 0) ) {
629 if(non_silent_mode) {
630 std::string msg = std::string(
"Read object \"") +
GetId() +
'@' + c->get_name() +
'\"';
632 Oks::warning_msg(msg.c_str()) <<
" skip attribute \"" << attr.
value() <<
"\", which is not defined in the schema\n";
636 info = info_i->second;
645 attr.
value()[0] != 0 &&
648 (attr.
value()[0] !=
'-')
656 num =
static_cast<int32_t
>(strtol(attr.
value(), &__sanity, 0));
667 if( __builtin_expect((!name_was_read), 0) ) {
677 catch (std::exception & e) {
682 if( __builtin_expect((a !=
nullptr), 1) ) {
686 if( __builtin_expect((check_re_read), 0) ) {
688 read_attributes->remove(a);
710 if(read_params.
format !=
'n')
711 d2.
read(read_params, &a2);
715 if(non_silent_mode) {
720 if(read_params.
format !=
'n')
721 dx->
read(read_params, a);
730 if(read_params.
format !=
'n')
731 d2.
read(read_params, &a2, num);
734 if(attr_is_closed ==
false)
735 d2.
read(&a2, read_params);
740 if(non_silent_mode) {
745 if(read_params.
format !=
'n')
746 dx->
read(read_params, a, num);
749 if(attr_is_closed ==
false)
750 dx->
read(a, read_params);
764 catch (std::exception & e) {
769 if( __builtin_expect((check_re_read), 0) ) {
782 if(read_params.
format !=
'n')
786 if(read_params.
format !=
'n')
787 OksData(read_params, &a2, num);
795 catch (std::exception & e) {
803 if(read_params.
format !=
'n')
808 std::string s(
"\'/attr\' is expected instead of \'");
811 throw std::runtime_error( s.c_str() );
817 catch (std::exception & e) {
844 if( __builtin_expect((c !=
nullptr), 1) ) {
846 info_i = c->p_data_info->find(i_name);
847 if( __builtin_expect((info_i == c->p_data_info->end() || info_i->second->relationship ==
nullptr), 0) ) {
848 if(non_silent_mode) {
849 std::string msg = std::string(
"Read object \"") +
GetId() +
'@' + c->get_name() +
'\"';
851 Oks::warning_msg(msg.c_str()) <<
" skip relationship \"" << attr.
value() <<
"\", which is not defined in the schema\n";
855 info = info_i->second;
861 else if(read_params.
format ==
'n') {
864 if( __builtin_expect((value.
m_class ==
nullptr && attr.
value_len() > 0), 0) ) {
876 num =
static_cast<int32_t
>(strtol(attr.
value(), &__sanity, 0));
888 catch (std::exception & e) {
897 if( __builtin_expect((r !=
nullptr), 1) ) {
903 if( __builtin_expect((check_re_read), 0) ) {
905 read_relationships->remove(r);
917 if(read_params.
format ==
'n')
918 d2.
read(&dummy, value);
920 d2.
read(read_params, &dummy);
924 if(read_params.
format ==
'n')
927 dx->
read(read_params, r);
935 if(read_params.
format ==
'n')
936 d2.
read(&dummy, read_params);
938 d2.
read(read_params, &dummy, num);
942 if(read_params.
format ==
'n')
943 dx->
read(r, read_params);
945 dx->
read(read_params, r, num);
952 catch (std::exception & e) {
969 if(read_params.
format !=
'n')
973 if(read_params.
format ==
'n')
982 catch (std::exception & e) {
990 if(read_params.
format !=
'n')
995 std::string s(
"\'/rel\' is expected instead of \'");
998 throw std::runtime_error( s.c_str() );
1004 catch (std::exception & e) {
1013 throw oks::FailedRead(std::string(
"object \"") +
uid.object_id +
'@' + c->get_name() +
'\"', e);
1015 catch (std::exception & e) {
1022 if( __builtin_expect((check_re_read), 0) ) {
1023 if(read_attributes) {
1024 if(!read_attributes->empty()) {
1025 for(
auto i = read_attributes->begin(); i != read_attributes->end(); i = read_attributes->erase(i)) {
1026 OksData d = (*i)->p_init_data;
1035 throw oks::ObjectInitError(
this, std::string(
"cannot reset default value of attribute \"") + (*i)->get_name() +
'\"', ex);
1040 delete read_attributes;
1043 if(read_relationships) {
1044 if(!read_relationships->empty()) {
1045 for(
auto i = read_relationships->begin(); i != read_relationships->end(); i = read_relationships->erase(i)) {
1049 if(d2 && *d2 != d) {
1055 throw oks::ObjectInitError(
this, std::string(
"cannot reset value of relationship \"") + (*i)->get_name() +
'\"', ex);
1060 delete read_relationships;
1068 throw std::runtime_error(
1069 " ***** Can't read objects of undefined class *****\n"
1070 " ***** from file saved in non-extended format. *****\n"
1071 " ***** Fix the problem first. Processing terminated. *****\n"
1075 if(c->p_all_attributes) {
1076 for(
const auto& i : *c->p_all_attributes) {
1080 if(i->get_is_multi_values()) {
1081 d.read(read_params, i,
__get_num(read_params));
1084 d.read(read_params, i);
1087 if(d !=
data[count]) {
1093 if(i->get_is_multi_values()) {
1097 data[count].read(read_params, i);
1105 if(c->p_all_relationships) {
1106 for(
const auto& i : *c->p_all_relationships) {
1111 d.read(read_params, i,
__get_num(read_params));
1114 d.read(read_params, i);
1117 if(d !=
data[count]) {
1127 data[count].read(read_params, i);
1141 std::ostringstream s;
1142 s <<
"Failed to read obj close tag (\'/" << read_params.
object_tag <<
"\' is expected)";
1143 throw std::runtime_error( s.str().c_str() );
1149 catch (std::exception & e) {
1184 if(!c->p_kernel->get_active_data()) {
1185 Oks::error_msg(
"OksObject::OksObject(const OksClass*, const char *)") <<
" Can not create new object since there is no active data file\n";
1190 uid.object_id = (object_id ? object_id :
"");
1196 uid.class_id =
nullptr;
1203 file->set_updated();
1211 Oks::error_msg(
"OksObject::OksObject(const OksObject&, const char *)") <<
" Can not create new object since there is no active data file\n";
1217 uid.object_id = (object_id ? object_id :
"");
1223 uid.class_id =
nullptr;
1228 int count = c->p_instance_size;
1229 int num_of_attr = c->p_all_attributes->size();
1232 while(j < num_of_attr) {
1238 std::list<OksRelationship *>::iterator i = c->p_all_relationships->begin();
1242 const char * relationshipName = r->get_name().c_str();
1254 data[j].data.LIST->push_back(uid_d);
1272 uid.class_id =
nullptr;
1278 file->set_updated();
1283 uid.class_id =
nullptr;
1285 memcpy(
static_cast<void *
>(&
data[
offset]),
static_cast<const void *
>(d),
sizeof(
OksData));
1300 if(
size_t data_size = c->p_instance_size *
sizeof(
OksData*)) {
1301 bzero(data, data_size);
1315 std::unique_ptr<std::ostringstream> error_text;
1319 for(OksClass::Map::const_iterator i = classes.begin(); i != classes.end(); ++i) {
1321 if(c->p_all_relationships ==
nullptr || c->p_all_relationships->empty())
continue;
1324 for(OksObject::Map::const_iterator j = objects->begin(); j != objects->end(); ++j) {
1325 size_t offset = c->number_of_all_attributes();
1326 for(std::list<OksRelationship *>::iterator k = c->p_all_relationships->begin(); k != c->p_all_relationships->end(); ++k, ++
offset) {
1334 for(
const auto& l : *d->data.LIST) {
1343 if(!error_text.get()) {
1344 error_text.reset(
new std::ostringstream());
1345 *error_text <<
"since it is referenced by:";
1347 *error_text <<
"\n * object " << ref <<
" via relationship \"" << (*k)->get_name() <<
'\"';
1354 if(error_text.get()) {
1385 static std::mutex s_mutex;
1386 static std::set<OksObject *, std::less<OksObject *> > oset;
1390 std::lock_guard lock(s_mutex);
1397 if(c->p_all_relationships && !c->p_all_relationships->empty()) {
1398 OksData *di =
data + c->number_of_all_attributes();
1400 for(std::list<OksRelationship *>::iterator i = c->p_all_relationships->begin(); i != c->p_all_relationships->end(); ++i, ++di) {
1403 if(r->get_is_composite() ==
false || k->
p_close_all ==
true)
continue;
1413 bool delete_obj(r->get_is_dependent() && !o->
p_rcr);
1416 std::lock_guard lock(s_mutex);
1417 delete_obj = (oset.find(o) == oset.end());
1422 d->data.OBJECT =
nullptr;
1427 for(
const auto& i2 : *d->data.LIST) {
1434 bool delete_obj(r->get_is_dependent() && !o->
p_rcr);
1437 std::lock_guard lock(s_mutex);
1438 delete_obj = (oset.find(o) == oset.end());
1443 i2->
data.OBJECT =
nullptr;
1453 for(
const auto& i : *c->p_indices)
1454 i.second->remove_obj(
this);
1457 int count = c->p_instance_size;
1458 while(count--)
data[count].Clear();
1473 for(std::list<OksRCR *>::const_iterator i =
p_rcr->begin(); i !=
p_rcr->end(); ++i) {
1481 std::lock_guard lock(s_mutex);
1495 file->set_updated();
1513 if(new_id ==
uid.object_id)
return;
1518 catch(std::exception& ex) {
1524 if(c->get_object(new_id)) {
1531 std::set<OksFile *> updated_files;
1532 std::list<OksObject *> updated_objects;
1534 updated_files.insert(
file);
1535 updated_objects.push_back(
this);
1539 for(OksClass::Map::const_iterator i = classes.begin(); i != classes.end(); ++i) {
1542 size_t d_end = c->p_instance_size;
1543 size_t d_begin = c->p_all_attributes->size();
1544 if(objs && (d_end != d_begin)) {
1545 for(OksObject::Map::const_iterator j = objs->begin(); j != objs->end(); ++j) {
1550 for(
size_t k = d_begin; k != d_end && o; ++k) {
1551 const OksData & d = o->data[k];
1553 updated_objects.push_back(o);
1554 updated_files.insert(o->file);
1559 for(OksData::List::const_iterator l = list.begin(); l != list.end(); ++l) {
1562 updated_objects.push_back(o);
1563 updated_files.insert(o->file);
1576 for(std::set<OksFile *>::const_iterator i = updated_files.begin(); i != updated_files.end(); ++i) {
1586 uid.object_id = new_id;
1593 for(std::set<OksFile *>::const_iterator i = updated_files.begin(); i != updated_files.end(); ++i) {
1594 (*i)->set_updated();
1598 for(std::list<OksObject *>::const_iterator i = updated_objects.begin(); i != updated_objects.end(); ++i) {
1599 (*i)->change_notify();
1610 if (o1 ==
nullptr || o2 ==
nullptr)
1626 while (count < uid.class_id->p_instance_size)
1661 s <<
"Object " << &o << std::endl;
1669 const std::list<OksAttribute *> * alist = c->all_attributes();
1671 if(alist && !alist->empty()) {
1672 s <<
" Attributes are:\n";
1674 for(std::list<OksAttribute *>::const_iterator i = alist->begin(); i != alist->end(); ++i) {
1676 s.setf(((*i)->get_format() ==
OksAttribute::Hex ? std::ios::hex : std::ios::oct), std::ios::basefield);
1677 s.setf(std::ios::showbase);
1680 s <<
" " << (*i)->get_name() <<
": " << *di++ << std::endl;
1683 s.setf(std::ios::dec, std::ios::basefield);
1684 s.unsetf(std::ios::showbase);
1689 s <<
" There are no attributes\n";
1696 const std::list<OksRelationship *> * rlist = c->all_relationships();
1698 if(rlist && !rlist->empty()) {
1699 s <<
" Relationships are:\n";
1701 for(std::list<OksRelationship *>::const_iterator i = rlist->begin(); i != rlist->end(); ++i)
1702 s <<
" " << (*i)->get_name() <<
": " << *di++ << std::endl;
1705 s <<
" There are no relationships\n";
1722 if (d.data.OBJECT && kernel.
is_dangling(d.data.OBJECT))
1724 d.data.OBJECT =
nullptr;
1727 return (d.data.OBJECT !=
nullptr);
1733 for (OksData::List::iterator i = d.data.LIST->begin(); i != d.data.LIST->end();)
1740 i = d.data.LIST->erase(i);
1748 return (!d.data.LIST->empty());
1761 const std::string * class_name =
nullptr;
1762 const std::string * object_id =
nullptr;
1766 class_name = &d.data.OBJECT->GetClass()->get_name();
1767 object_id = &d.data.OBJECT->GetId();
1771 class_name = &d.data.UID.class_id->get_name();
1772 object_id = d.data.UID.object_id;
1776 class_name = d.data.UID2.class_id;
1777 object_id = d.data.UID2.object_id;
1804 for (
const auto& a : *alist)
1809 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')))
1822 if (a->get_is_multi_values() ==
false)
1829 if (d.data.LIST->empty())
1840 for (
const auto& x : *d.data.LIST)
1856 xmls.
get_stream().setf(std::ios::dec, std::ios::basefield);
1857 xmls.
get_stream().unsetf(std::ios::showbase);
1865 for (
const auto& r : *rlist)
1887 for (
const auto& x : *rel_data.
data.
LIST)
1909 catch (std::ios_base::failure & ex)
1913 catch (std::exception & ex)
1926 OksDataInfo::Map::const_iterator i =
uid.class_id->p_data_info->find(name);
1928 if(i ==
uid.class_id->p_data_info->end()) {
1929 std::ostringstream text;
1930 text <<
"object " <<
this <<
" has no attribute \"" << name <<
'\"';
1946 if(
uid.class_id->get_kernel()->get_silence_mode() ==
false) {
1947 Oks::warning_msg(
"OksObject::SetAttributeValue(const OksDataInfo *, OksData *)")
1948 <<
" * ODI attribute name: \'" << a->
get_name() <<
"\'\n"
1949 " * ODI data offset: \'" <<
offset <<
"\'\n"
1950 " * OKS data (new): \'" << *d <<
"\' type: " << (int)d->type <<
"\n"
1952 " Object " <<
this <<
":\n"
1953 " Convert attribute \"" << a->
get_name() <<
"\" value since the OksData::type is invalid\n";
1978 if(
uid.class_id->p_indices) {
1979 OksIndex::Map::iterator j =
uid.class_id->p_indices->find(a);
1980 if(j !=
uid.class_id->p_indices->end()) {
1987 if(i) i->insert(
this);
1997 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
1999 if(i ==
uid.class_id->p_data_info->end()) {
2000 std::ostringstream text;
2001 text <<
"object " <<
this <<
" has no attribute \"" << name <<
'\"';
2011 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2013 if(i ==
uid.class_id->p_data_info->end()) {
2014 std::ostringstream text;
2015 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2028 this,
true, r->get_name(),
2029 "set to (null) is not allowed since the relationship has non-zero low cardinality constraint"
2038 if(!class_type)
return;
2040 const OksClass * rel_class_type = r->p_class_type;
2042 if(class_type != rel_class_type) {
2045 if(super_classes && !super_classes->empty()) {
2046 for(
const auto& i : *super_classes) {
2047 if(rel_class_type == i)
return;
2051 std::ostringstream text;
2052 text <<
"set to an object of class \"" << class_type->get_name() <<
"\" is not allowed since the relationship's class type is \""
2053 << r->get_type() <<
"\" and the class \"" << class_type->get_name() <<
"\" has no such superclass";
2069 std::ostringstream text;
2071 <<
"offset: " <<
offset <<
"; new: \'" << *d <<
"\'; old:" <<
data[
offset] <<
'\'';
2084 if(add_obj != rm_obj) {
2085 if(add_obj) added_objs.insert(add_obj);
2086 if(rm_obj) removed_objs.insert(rm_obj);
2092 if(skip_non_null_check ==
false)
check_non_null(r, d->data.OBJECT);
2096 if(d->data.LIST->empty()) {
2099 this,
true, r->get_name(),
2100 "set to empty list is not allowed since the relationship has non-zero low cardinality constraint"
2105 for(
const auto& i : *d->data.LIST) {
2121 added_objs.insert(o2);
2128 this,
true, r->get_name(),
2129 "the OKS data type is invalid (must be a list of objects or an object)"
2141 removed_objs.insert(i->data.OBJECT);
2149 for(
const auto& i : removed_objs) {
2150 if(added_objs.find(i) == added_objs.end()) {
2151 TLOG_DEBUG(4) <<
"object " << i <<
" was removed from relationship";
2152 i->remove_RCR(
this, r);
2159 for(OksObject::FSet::const_iterator i = added_objs.begin(); i != added_objs.end(); ++i) {
2161 if(removed_objs.find(add_obj) == removed_objs.end()) {
2162 TLOG_DEBUG(4) <<
"object " << add_obj <<
" was added to relationship";
2170 for(OksObject::FSet::const_iterator j = added_objs.begin(); j != i; ++j) {
2171 if(removed_objs.find(*j) == removed_objs.end()) {
2172 (*j)->remove_RCR(
this, r);
2176 for(OksObject::FSet::const_iterator j = removed_objs.begin(); j != removed_objs.end(); ++j) {
2177 if(added_objs.find(*j) == added_objs.end()) {
2196 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2198 if(i ==
uid.class_id->p_data_info->end()) {
2199 std::ostringstream text;
2200 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2215 std::ostringstream text;
2216 text <<
"cannot set value " <<
object <<
" since the relationship has \'many\' high cardinality constraint";
2230 d.data.OBJECT->remove_RCR(
this, r);
2235 object->add_RCR(
this, r);
2240 try { d.data.OBJECT->add_RCR(
this, r); }
catch(
oks::exception& ex2) { ; }
2254 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2256 if(i ==
uid.class_id->p_data_info->end()) {
2257 std::ostringstream text;
2258 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2271 return ((d2->
data.
OBJECT == d->data.OBJECT) ?
true :
false);
2273 const std::string& object_id =
2275 d->type ==
OksData::uid2_type ? *(
static_cast<std::string*
>(d->data.UID2.object_id)) :
2276 *(
static_cast<std::string*
>(d->data.UID.object_id));
2278 const std::string& object_id2 =
2283 if(object_id != object_id2)
return false;
2295 if(pclass_id && pclass_id2)
return (pclass_id == pclass_id2 ?
true :
false);
2297 const std::string& class_id =
2298 (pclass_id ? pclass_id->
get_name() : *(
static_cast<std::string*
>(d->data.UID2.class_id)));
2300 const std::string& class_id2 =
2303 return (class_id == class_id2 ?
true :
false);
2320 std::ostringstream text;
2321 text <<
"cannot add value " <<
object <<
" since the relationship has no \'many\' high cardinality constraint";
2326 object->add_RCR(
this, r);
2343 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2345 if(i ==
uid.class_id->p_data_info->end()) {
2346 std::ostringstream text;
2347 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2365 std::ostringstream text;
2366 text <<
"cannot remove object " <<
object <<
" since the relationship has no \'many\' high cardinality constraint";
2374 for(OksData::List::iterator i = list->begin(); i != list->end();) {
2378 object->remove_RCR(
this, r);
2387 std::ostringstream text;
2388 text <<
"cannot remove object " <<
object <<
" since the relationship\'s value has no such object";
2396 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2398 if(i ==
uid.class_id->p_data_info->end()) {
2399 std::ostringstream text;
2400 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2410 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2412 if(i ==
uid.class_id->p_data_info->end()) {
2413 std::ostringstream text;
2414 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2424 if(object_id.empty() || class_id.empty()) {
2429 data[
offset].data.OBJECT->remove_RCR(
this, r);
2439 OksClass *c =
uid.class_id->p_kernel->find_class(class_id);
2444 else if(r->get_type() != class_id) {
2445 std::ostringstream text;
2446 text <<
"cannot set value \"" << object_id <<
'@' << class_id <<
"\" since the class \"" << class_id
2447 <<
"\" is not defined and it is impossible to check its validity for given type of relationship";
2452 std::ostringstream text;
2453 text <<
"cannot set object \"" << object_id <<
'@' << class_id <<
"\" since the relationship has \'many\' high cardinality constraint";
2459 if(c) o = c->get_object(object_id);
2468 data[
offset].data.OBJECT->remove_RCR(
this, r);
2481 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2483 if(i ==
uid.class_id->p_data_info->end()) {
2484 std::ostringstream text;
2485 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2492 if(class_id.empty() || object_id.empty()) {
2496 const std::string& r_class_type = r->get_type();
2499 OksClass *c =
uid.class_id->p_kernel->find_class(class_id);
2504 else if(r_class_type != class_id) {
2505 std::ostringstream text;
2506 text <<
"cannot add value \"" << object_id <<
'@' << class_id <<
"\" since the class \"" << class_id
2507 <<
"\" is not defined and it is impossible to check its validity for given type of relationship";
2512 std::ostringstream text;
2513 text <<
"cannot add object \"" << object_id <<
'@' << class_id <<
"\" since the relationship has no \'many\' high cardinality constraint";
2519 if(c) o = c->get_object(object_id);
2535 OksDataInfo::Map::iterator i =
uid.class_id->p_data_info->find(name);
2537 if(i ==
uid.class_id->p_data_info->end()) {
2538 std::ostringstream text;
2539 text <<
"object " <<
this <<
" has no relationship \"" << name <<
'\"';
2546 if(object_id.empty() || class_id.empty()) {
2551 std::ostringstream text;
2552 text <<
"cannot remove object \"" << object_id <<
'@' << class_id <<
"\" since the relationship has no \'many\' high cardinality constraint";
2557 OksData d(class_id, object_id);
2560 for(OksData::List::iterator j = list->begin(); j != list->end();) {
2572 std::ostringstream text;
2573 text <<
"cannot remove object \"" << object_id <<
'@' << class_id <<
"\" since the relationship\'s value has no such object";
2581 if(r->get_is_composite() ==
false)
return;
2583 TLOG_DEBUG(4) <<
"object " <<
this <<
" adds RCR to object " << o <<
" throught relationship \"" << r->get_name() <<
'\"';
2586 p_rcr =
new std::list<OksRCR *>();
2589 for(
const auto& i : *
p_rcr) {
2590 if(i->relationship == r) {
2592 TLOG_DEBUG(4) <<
"[this=" <<
this <<
", o=" << o <<
", r=\"" << r->get_name() <<
"\"]: such RCR was already set.";
2595 else if(r->get_is_exclusive()) {
2609 TLOG_DEBUG(4) <<
"object " <<
this <<
" removes RCR from object " << o <<
" through " << r->get_name();
2611 if(r->get_is_composite() ==
false || !
p_rcr)
return;
2613 for(std::list<OksRCR *>::iterator i =
p_rcr->begin(); i !=
p_rcr->end(); ++i) {
2623 if(
p_rcr->empty()) {
2637 if(d->data.UID.class_id && !d->data.UID.object_id->empty()) {
2638 c = d->data.UID.class_id;
2639 o = c->get_object(d->data.UID.object_id);
2647 if(d->data.UID2.class_id->empty() || d->data.UID2.object_id->empty()) {
2652 c = info.k->find_class(*d->data.UID2.class_id);
2655 o = c->get_object(d->data.UID2.object_id);
2658 std::ostringstream text;
2659 text <<
"Class of object " << *d <<
" is not defined";
2664 if(c != info.r->p_class_type) {
2666 for(OksClass::FList::const_iterator i = slist->begin(); i != slist->end(); ++i) {
2667 if(info.r->p_class_type == *i) {
2674 std::ostringstream text;
2675 text <<
"The relationship has class type \"" << info.r->get_type() <<
"\" and the referenced object " << *d <<
" is not of that class or derived one";
2683 std::ostringstream text;
2684 text <<
"Cannot find object " << *d;
2693 std::ostringstream text;
2694 text <<
"Failed to set relationship value " << o;
2709 std::ostringstream&
add();
2716 else {
p_warnings =
new std::ostringstream();}
2725 add() <<
" * object " << d <<
" via relationship \"" << r->get_name() <<
'\"';
2731 add() <<
" * relationship \"" << r->get_name() <<
"\" has non-zero low cardinality constraint, but it is empty";
2740 if(c->p_all_relationships->empty())
return;
2743 info.k = c->p_kernel;
2746 OksData * d(
data + c->number_of_all_attributes());
2750 for (
auto & i : (*c->p_all_relationships))
2756 if (i->get_low_cardinality_constraint() ==
OksRelationship::One && d->data.OBJECT ==
nullptr) { warnings.
add(i); }
2760 if (d->data.UID.object_id ==
nullptr)
2777 if (d->data.LIST->empty())
2783 for (
const auto& i2 : *d->data.LIST)
2802 if (i->get_low_cardinality_constraint() ==
OksRelationship::One && d->data.UID2.object_id ==
nullptr) { warnings.
add(i); }
2819 std::ostringstream text;
2822 text <<
"There " << s1 <<
" " << warnings.
p_warnings_count <<
" unresolved reference" << s2 <<
" from object " <<
this
2832 const size_t num_of_attrs (
uid.class_id->number_of_all_attributes());
2833 const size_t num_of_rels (
uid.class_id->number_of_all_relationships());
2837 for(
size_t i = 0; i < num_of_rels; ++i) {
2844 if(o && o->
file == f) {
2846 std::cout <<
"- unbind_file(\'" << f->get_full_file_name() <<
"\') in " <<
this <<
": replace " << *d;
2850 if(verbose) std::cout <<
" by " << *d << std::endl;
2854 for(
const auto& j : *d->data.LIST) {
2858 if(o && o->
file == f) {
2860 std::cout <<
"+ unbind_file(\'" << f->get_full_file_name() <<
"\') in " <<
this <<
": replace " << *j;
2864 if(verbose) std::cout <<
" by " << *j << std::endl;
2876 return uid.class_id->p_kernel->p_change_object_notify_fn;
2924 if(includes.find(o2->
get_file()) == includes.end()) {
2925 if(
GetClass()->get_kernel()->get_silence_mode() ==
false) {
2927 msg <<
": no files inclusion path between referenced objects:\n"
2932 for(std::set<OksFile *>::const_iterator j = includes.begin(); j != includes.end(); ++j) {
2933 std::cerr <<
" * \'" << (*j)->get_full_file_name() <<
"\'\n";
2949 std::ostringstream text;
2951 if(result.empty()) {
2952 text <<
" * object " <<
obj <<
" has dangling references:\n";
2955 text <<
" - object " << d <<
" referenced via \'" << r.get_name() <<
"\'\n";
2957 result += text.str();
2976 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
3000 bool return_value =
true;
3012 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
3014 if(
OksObject * o2 = (*li)->data.OBJECT) {
3021 if(d->IsConsistent(odi.
relationship,
this,
"ERROR") ==
false) {
3022 return_value =
false;
3032 if(
GetClass()->get_kernel()->get_silence_mode() ==
false) {
3034 "ERROR: the schema file is not included for object " <<
this <<
".\n"
3036 " cannot be loaded or edited without inclusion of additional files.\n"
3037 " The file shall explicitly or implicitly (i.e. via other included files) include schema file\n"
3045 return return_value;
3060static void _references(
const OksObject *
obj,
unsigned long recursion_depth, RefData& data);
3068 std::pair<OksObject::FSet::iterator,bool> ret = data.tested_objs.insert(
const_cast<OksObject *
>(o));
3070 if(ret.second==
true) {
3071 if(data.classes ==
nullptr || data.classes->find(
const_cast<OksClass *
>(o->
GetClass())) != data.classes->end()) {
3072 data.refs.insert(
const_cast<OksObject *
>(o));
3086 if(recursion_depth == 0)
return;
3088 size_t l1 =
obj->GetClass()->number_of_all_attributes();
3089 size_t l2 = l1 +
obj->GetClass()->number_of_all_relationships();
3093 OksData * d(
obj->GetRelationshipValue(&odi));
3101 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
3119 std::lock_guard lock(
uid.class_id->p_kernel->p_objects_refs_mutex);
3129 TLOG_DEBUG(2) <<
"OksObject::references(" <<
this <<
", " << recursion_depth <<
") returns " << refs.size() <<
" objects";
3136 bool any_name = (name ==
"*");
3142 for(OksClass::Map::const_iterator i = all_classes.begin(); i != all_classes.end(); ++i) {
3144 if(any_name || c->find_relationship(name) !=
nullptr) {
3146 for(OksObject::Map::const_iterator j = objs->begin(); j != objs->end(); ++j) {
3148 unsigned short l1, l2;
3151 l1 = c->number_of_all_attributes();
3152 l2 = l1 + c->number_of_all_relationships();
3155 l1 = c->data_info(name)->offset;
3164 if(
this == d->data.OBJECT) {
3166 result->push_back(o);
3172 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
3177 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
std::list< OksClass *, boost::fast_pool_allocator< OksClass * > > FList
OksKernel * get_kernel() const noexcept
const std::string & get_name() const noexcept
size_t number_of_all_attributes() const noexcept
OksClass(const std::string &name, OksKernel *kernel, bool transient=false)
Create OKS class.
std::map< const char *, OksClass *, SortStr > Map
OksFile * get_file() const noexcept
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
OksData * GetRelationshipValue(const std::string &) const
Get value of relationship by name.
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 *)
std::unordered_set< OksObject *, oks::hash_obj_ptr, oks::equal_obj_ptr > FSet
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[]
void(* notify_obj)(OksObject *, void *)
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[]
std::list< OksObject *, boost::fast_pool_allocator< OksObject * > > FList
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
std::unordered_map< const std::string *, OksObject *, oks::hash_str, oks::equal_str > Map
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
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)
#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.
const OksClass * class_id
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
const OksClass * class_id
struct dunedaq::oks::OksData::Data::@266171337063116272021017117226020166361213322350 UID
struct dunedaq::oks::OksData::Data::@226266061051241020017305361066131172152317024337 UID2