LCOV - code coverage report
Current view: top level - oks/src - relationship.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 19.1 % 188 36
Test Date: 2025-12-21 13:07:08 Functions: 18.8 % 16 3

            Line data    Source code
       1              : #define _OksBuildDll_
       2              : 
       3              : #include "oks/relationship.hpp"
       4              : #include "oks/xml.hpp"
       5              : #include "oks/class.hpp"
       6              : #include "oks/kernel.hpp"
       7              : #include "oks/cstring.hpp"
       8              : 
       9              : #include <sstream>
      10              : 
      11              : namespace dunedaq {
      12              : namespace oks {
      13              : 
      14              : const char OksRelationship::relationship_xml_tag[]  = "relationship";
      15              : const char OksRelationship::name_xml_attr[]         = "name";
      16              : const char OksRelationship::description_xml_attr[]  = "description";
      17              : const char OksRelationship::class_type_xml_attr[]   = "class-type";
      18              : const char OksRelationship::low_cc_xml_attr[]       = "low-cc";
      19              : const char OksRelationship::high_cc_xml_attr[]      = "high-cc";
      20              : const char OksRelationship::is_composite_xml_attr[] = "is-composite";
      21              : const char OksRelationship::is_exclusive_xml_attr[] = "is-exclusive";
      22              : const char OksRelationship::is_dependent_xml_attr[] = "is-dependent";
      23              : const char OksRelationship::ordered_xml_attr[]      = "ordered";
      24              : 
      25              : 
      26              : OksRelationship::CardinalityConstraint
      27         9344 : OksRelationship::str2card(const char * s) noexcept
      28              : {
      29         9344 :   return (
      30         9344 :     oks::cmp_str3(s, "one")  ? One :
      31         4944 :     oks::cmp_str4(s, "zero") ? Zero :
      32              :     Many
      33         9344 :   );
      34              : }
      35              : 
      36              : const char *
      37            0 : OksRelationship::card2str(CardinalityConstraint cc) noexcept
      38              : {
      39            0 :   return (
      40            0 :     cc == Zero ? "zero" :
      41            0 :     cc == One  ? "one" :
      42              :     "many"
      43            0 :   );
      44              : }
      45              : 
      46            0 : OksRelationship::OksRelationship(const std::string& nm, OksClass * p) :
      47            0 :   p_name           (nm),
      48            0 :   p_low_cc         (Zero),
      49            0 :   p_high_cc        (Many),
      50            0 :   p_composite      (false),
      51            0 :   p_exclusive      (false),
      52            0 :   p_dependent      (false),
      53            0 :   p_class          (p),
      54            0 :   p_class_type     (nullptr),
      55            0 :   p_ordered        (false)
      56              : {
      57            0 :   oks::validate_not_empty(p_name, "relationship name");
      58            0 : }
      59              : 
      60            0 : OksRelationship::OksRelationship(const std::string& nm, const std::string& rc,
      61              :                                  CardinalityConstraint l_cc, CardinalityConstraint h_cc,
      62            0 :                                  bool cm, bool excl, bool dp, const std::string& desc, OksClass * p) :
      63            0 :   p_name           (nm),
      64            0 :   p_rclass         (rc),
      65            0 :   p_low_cc         (l_cc),
      66            0 :   p_high_cc        (h_cc),
      67            0 :   p_composite      (cm),
      68            0 :   p_exclusive      (excl),
      69            0 :   p_dependent      (dp),
      70            0 :   p_description    (desc),
      71            0 :   p_class          (p),
      72            0 :   p_class_type     (nullptr),
      73            0 :   p_ordered        (false)
      74              : {
      75            0 :   oks::validate_not_empty(p_name, "relationship name");
      76            0 :   oks::validate_not_empty(p_rclass, "relationship class");
      77            0 : }
      78              : 
      79              : bool
      80          252 : OksRelationship::operator==(const class OksRelationship &r) const
      81              : {
      82          252 :   return (
      83          252 :     ( this == &r ) ||
      84              :     (
      85            0 :       ( p_name == r.p_name ) &&
      86            0 :       ( p_rclass == r.p_rclass ) &&
      87            0 :       ( p_low_cc == r.p_low_cc ) &&
      88              :       ( p_high_cc == r.p_high_cc ) &&
      89              :       ( p_composite == r.p_composite ) &&
      90            0 :       ( p_exclusive == r.p_exclusive ) &&
      91            0 :       ( p_dependent == r.p_dependent ) &&
      92            0 :       ( p_description == r.p_description ) &&
      93            0 :       ( p_ordered == r.p_ordered )
      94              :    )
      95          252 :   );
      96              : }
      97              : 
      98              : std::ostream&
      99            0 : operator<<(std::ostream& s, const OksRelationship& r)
     100              : {
     101            0 :   s << "Relationship name: \"" << r.p_name << "\"\n"
     102            0 :        " class type: \"" << r.p_rclass << "\"\n"
     103            0 :        " low cardinality constraint is " << OksRelationship::card2str(r.p_low_cc) << "\n"
     104            0 :        " high cardinality constraint is " << OksRelationship::card2str(r.p_high_cc) << "\n"
     105            0 :        " is" << (r.p_composite == true ? "" : " not") << " composite reference\n"
     106            0 :        " is" << (r.p_exclusive == true ? "" : " not") << " exclusive reference\n"
     107            0 :        " is " << (r.p_dependent == true ? "dependent" : "shared") << " reference\n"
     108            0 :        " has description: \"" << r.p_description << "\"\n"
     109            0 :        " is " << (r.p_ordered == true ? "ordered" : "unordered") << std::endl;
     110              : 
     111            0 :   return s;
     112              : }
     113              : 
     114              : 
     115              : void
     116            0 : OksRelationship::save(OksXmlOutputStream& s) const
     117              : {
     118            0 :   s.put("  ");
     119              : 
     120            0 :   s.put_start_tag(relationship_xml_tag, sizeof(relationship_xml_tag) - 1);
     121              : 
     122            0 :   s.put_attribute(name_xml_attr, sizeof(name_xml_attr) - 1, p_name.c_str());
     123              : 
     124            0 :   if (!p_description.empty())
     125            0 :     s.put_attribute(description_xml_attr, sizeof(description_xml_attr) - 1, p_description.c_str());
     126              : 
     127            0 :   s.put_attribute(class_type_xml_attr, sizeof(class_type_xml_attr) - 1, p_rclass.c_str());
     128            0 :   s.put_attribute(low_cc_xml_attr, sizeof(low_cc_xml_attr) - 1, card2str(p_low_cc));
     129            0 :   s.put_attribute(high_cc_xml_attr, sizeof(high_cc_xml_attr) - 1, card2str(p_high_cc));
     130            0 :   s.put_attribute(is_composite_xml_attr, sizeof(is_composite_xml_attr) - 1, oks::xml::bool2str(p_composite));
     131            0 :   s.put_attribute(is_exclusive_xml_attr, sizeof(is_exclusive_xml_attr) - 1, oks::xml::bool2str(p_exclusive));
     132            0 :   s.put_attribute(is_dependent_xml_attr, sizeof(is_dependent_xml_attr) - 1, oks::xml::bool2str(p_dependent));
     133              : 
     134            0 :   if (p_ordered)
     135            0 :     s.put_attribute(ordered_xml_attr, sizeof(ordered_xml_attr) - 1, oks::xml::bool2str(p_ordered));
     136              : 
     137            0 :   s.put_end_tag();
     138            0 : }
     139              : 
     140              : 
     141         4672 : OksRelationship::OksRelationship(OksXmlInputStream& s, OksClass *parent) :
     142         4672 :   p_low_cc         (Zero),
     143         4672 :   p_high_cc        (Many),
     144         4672 :   p_composite      (false),
     145         4672 :   p_exclusive      (false),
     146         4672 :   p_dependent      (false),
     147         4672 :   p_class          (parent),
     148         4672 :   p_class_type     (nullptr),
     149         4672 :   p_ordered        (false)
     150              : {
     151        39652 :   try {
     152        74632 :     while(true) {
     153        39652 :       OksXmlAttribute attr(s);
     154              : 
     155              :         // check for close of tag
     156              :       
     157        39652 :       if(oks::cmp_str1(attr.name(), "/")) { break; }
     158              : 
     159              : 
     160              :         // check for known oks-relationship' attributes
     161              : 
     162        34980 :       else if(oks::cmp_str4(attr.name(), name_xml_attr)) p_name.assign(attr.value(), attr.value_len());
     163        30308 :       else if(oks::cmp_str11(attr.name(), description_xml_attr)) p_description.assign(attr.value(), attr.value_len());
     164        28041 :       else if(oks::cmp_str10(attr.name(), class_type_xml_attr)) p_rclass.assign(attr.value(), attr.value_len());
     165        23369 :       else if(oks::cmp_str6(attr.name(), low_cc_xml_attr)) p_low_cc = str2card(attr.value());
     166        18697 :       else if(oks::cmp_str7(attr.name(), high_cc_xml_attr)) p_high_cc = str2card(attr.value());
     167        14025 :       else if(oks::cmp_str12(attr.name(), is_composite_xml_attr)) p_composite = oks::xml::str2bool(attr.value());
     168         9353 :       else if(oks::cmp_str12(attr.name(), is_exclusive_xml_attr)) p_exclusive = oks::xml::str2bool(attr.value());
     169         4681 :       else if(oks::cmp_str12(attr.name(), is_dependent_xml_attr)) p_dependent = oks::xml::str2bool(attr.value());
     170            9 :       else if(oks::cmp_str7(attr.name(), ordered_xml_attr)) p_ordered = oks::xml::str2bool(attr.value());
     171            0 :       else if(!strcmp(attr.name(), "multi-value-implementation")) {
     172            0 :         s.error_msg("OksRelationship::OksRelationship(OksXmlInputStream&)")
     173            0 :              << "Obsolete oks-relationship\'s attribute \'" << attr.name() << "\'\n";
     174              :       }
     175              :       else {
     176            0 :         s.throw_unexpected_attribute(attr.name());
     177              :       }
     178        34980 :     }
     179              :   }
     180            0 :   catch(oks::exception & e) {
     181            0 :     throw oks::FailedRead("xml attribute", e);
     182            0 :   }
     183            0 :   catch (std::exception & e) {
     184            0 :     throw oks::FailedRead("xml attribute", e.what());
     185            0 :   }
     186              : 
     187              : 
     188              :     // check validity of read values
     189              : 
     190         4672 :   try {
     191         4672 :     oks::validate_not_empty(p_name, "relationship name");
     192         4672 :     oks::validate_not_empty(p_rclass, "relationship class");
     193              :   }
     194            0 :   catch(std::exception& ex) {
     195            0 :     throw oks::FailedRead("oks relationship", oks::BadFileData(ex.what(), s.get_line_no(), s.get_line_pos()));
     196            0 :   }
     197         4672 : }
     198              : 
     199              : 
     200              : void
     201            0 : OksRelationship::set_name(const std::string& new_name)
     202              : {
     203              :     // ignore when name is the same
     204              : 
     205            0 :   if(p_name == new_name) return;
     206              : 
     207              : 
     208              :     // additional checks are required,
     209              :     // if the relationship already belongs to some class
     210              : 
     211            0 :   if(p_class) {
     212              : 
     213              :       // check maximum allowed length for relationship name
     214              : 
     215            0 :     try {
     216            0 :       oks::validate_not_empty(new_name, "name");
     217              :     }
     218            0 :     catch(std::exception& ex) {
     219            0 :       throw oks::SetOperationFailed("OksRelationship::set_name", ex.what());
     220            0 :     }
     221              : 
     222              : 
     223              :       // having a direct relationship with the same name is an error
     224              : 
     225            0 :     if(p_class->find_direct_relationship(new_name) != 0) {
     226            0 :       std::ostringstream text;
     227            0 :       text << "Class \"" << p_class->get_name() << "\" already has direct relationship \"" << new_name << '\"';
     228            0 :       throw oks::SetOperationFailed("OksRelationship::set_name", text.str());
     229            0 :     }
     230              : 
     231              : 
     232              :       // check possibility to lock the file
     233              : 
     234            0 :     p_class->lock_file("OksRelationship::set_name");
     235              : 
     236              : 
     237              :       // probably a non-direct relationship already exists
     238              : 
     239            0 :     OksRelationship * r = p_class->find_relationship(new_name);
     240              : 
     241              : 
     242              :       // change the name
     243              : 
     244            0 :     p_name = new_name;
     245              : 
     246              : 
     247              :       // registrate the change
     248              : 
     249            0 :     p_class->registrate_class_change(OksClass::ChangeRelationshipsList, (const void *)r);
     250              :   }
     251              :   else {
     252            0 :     p_name = new_name;
     253              :   }
     254              : }
     255              : 
     256              : void
     257            0 : OksRelationship::set_type(const std::string& cn)
     258              : {
     259            0 :   if(p_rclass == cn) return;
     260              : 
     261            0 :   if(!p_class || !p_class->p_kernel || (p_class_type = p_class->p_kernel->find_class(cn)) != 0) {
     262            0 :     if(p_class) p_class->lock_file("OksRelationship::set_type");
     263              : 
     264            0 :     p_rclass = cn;
     265              : 
     266            0 :     if(p_class) {
     267            0 :       p_class->registrate_class_change(OksClass::ChangeRelationshipClassType, (const void *)this);
     268            0 :       p_class->registrate_relationship_change(this);
     269              :     }
     270              :   }
     271              :   else {
     272            0 :     std::ostringstream text;
     273            0 :     text << "cannot find class \"" << cn << '\"';
     274            0 :     throw oks::SetOperationFailed("OksRelationship::set_type", text.str());
     275            0 :   }
     276              : }
     277              :         
     278              : void
     279            0 : OksRelationship::set_description(const std::string& desc)
     280              : {
     281            0 :   if(p_description != desc) {
     282            0 :     if(p_class) p_class->lock_file("OksRelationship::set_description");
     283              : 
     284            0 :     p_description = desc;
     285              : 
     286            0 :     if(p_class) p_class->registrate_class_change(OksClass::ChangeRelationshipDescription, (const void *)this);
     287              :   }
     288            0 : }
     289              :         
     290              : void
     291            0 : OksRelationship::set_low_cardinality_constraint(CardinalityConstraint l_cc)
     292              : {
     293            0 :   if(p_low_cc != l_cc) {
     294            0 :     if(p_class) p_class->lock_file("OksRelationship::set_low_cardinality_constraint");
     295              : 
     296            0 :     CardinalityConstraint old_cc = p_low_cc;
     297              : 
     298            0 :     p_low_cc = l_cc;
     299              : 
     300            0 :     if(p_class) {
     301            0 :       p_class->registrate_class_change(OksClass::ChangeRelationshipLowCC, (const void *)this);
     302              :                 
     303            0 :       if(p_low_cc == Many || old_cc == Many) p_class->registrate_relationship_change(this);
     304              :     }
     305              :   }
     306            0 : }
     307              :         
     308              : void
     309            0 : OksRelationship::set_high_cardinality_constraint(CardinalityConstraint h_cc)
     310              : {
     311            0 :   if(p_high_cc != h_cc) {
     312            0 :     if(p_class) p_class->lock_file("OksRelationship::set_high_cardinality_constraint");
     313              : 
     314            0 :     CardinalityConstraint old_cc = p_high_cc;
     315              : 
     316            0 :     p_high_cc = h_cc;
     317              :         
     318            0 :     if(p_class) {
     319            0 :       p_class->registrate_class_change(OksClass::ChangeRelationshipHighCC, (const void *)this);
     320              : 
     321            0 :       if(p_high_cc == Many || old_cc == Many) p_class->registrate_relationship_change(this);
     322              :     }
     323              :   }
     324            0 : }
     325              :         
     326              : void
     327            0 : OksRelationship::set_is_composite(bool cm)
     328              : {
     329            0 :   if(p_composite != cm) {
     330            0 :     if(p_class) p_class->lock_file("OksRelationship::set_is_composite");
     331              : 
     332            0 :     p_composite = cm;
     333              : 
     334            0 :     if(p_class) p_class->registrate_class_change(OksClass::ChangeRelationshipComposite, (const void *)this);
     335              :   }
     336            0 : }
     337              :         
     338              : void
     339            0 : OksRelationship::set_is_exclusive(bool ex)
     340              : {
     341            0 :   if(p_exclusive != ex) {
     342            0 :     if(p_class) p_class->lock_file("OksRelationship::set_is_exclusive");
     343              : 
     344            0 :     p_exclusive = ex;
     345              : 
     346            0 :     if(p_class) p_class->registrate_class_change(OksClass::ChangeRelationshipExclusive, (const void *)this);
     347              :   }
     348            0 : }
     349              :         
     350              : void
     351            0 : OksRelationship::set_is_dependent(bool dp)
     352              : {
     353            0 :   if(p_dependent != dp) {
     354            0 :     if(p_class) p_class->lock_file("OksRelationship::set_is_dependent");
     355              : 
     356            0 :     p_dependent = dp;
     357              : 
     358            0 :     if(p_class) p_class->registrate_class_change(OksClass::ChangeRelationshipDependent, (const void *)this);
     359              :   }
     360            0 : }
     361              : 
     362              : } // namespace oks
     363              : } // namespace dunedaq
        

Generated by: LCOV version 2.0-1