LCOV - code coverage report
Current view: top level - oksutils/apps - oks_tutorial.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 192 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 7 0

            Line data    Source code
       1              : //
       2              : // DUNE DAQ modification notice:
       3              : // This file has been modified from the original ATLAS oks_utils source for the DUNE DAQ project.
       4              : // Fork baseline commit: c2e7dfc7 (2022-03-30).
       5              : // Renamed since fork: yes (from src/bin/oks_tutorial.cpp to apps/oks_tutorial.cxx).
       6              : //
       7              : 
       8              : /************************************************************************
       9              :  *                                                                       *
      10              :  * tutorial.cpp                                                          *
      11              :  *        Explains basics of OKS C++ API including:                      *
      12              :  *                - kernel initialization                                *
      13              :  *                - schema design                                        *
      14              :  *                - data creation                                        *
      15              :  *                - data manipulation                                    *
      16              :  *                - notification                                         *
      17              :  *                                                                       *
      18              :  * Author Igor Soloviev                                                  *
      19              :  *                                                                       *
      20              :  * Created: 14 Oct 1996                                                  *
      21              :  *                                                                       *
      22              :  * Modified:                                                             *
      23              :  *        11 Feb 1998                                                    *
      24              :  *                - add database quering                                 *
      25              :  *                                                                       *
      26              :  ************************************************************************/
      27              : 
      28              : #include <boost/date_time/gregorian/gregorian.hpp>
      29              : 
      30              : #include "oks/attribute.hpp"
      31              : #include "oks/class.hpp"
      32              : #include "oks/exceptions.hpp"
      33              : #include "oks/kernel.hpp"
      34              : #include "oks/object.hpp"
      35              : #include "oks/query.hpp"
      36              : #include "oks/relationship.hpp"
      37              : 
      38              : using namespace dunedaq;
      39              : using namespace dunedaq::oks;
      40              : 
      41              : //
      42              : // This function sets attribute values of class 'Person'
      43              : //
      44              : 
      45              : void
      46            0 : setPersonValues(OksObject* o,                    // OKS object describing person
      47              :                 const char* name,                // new person name
      48              :                 boost::gregorian::date birthday, // new person birthday
      49              :                 const char* familySituation      // new person family situation
      50              : )
      51              : {
      52            0 :   OksData d; // creates OKS data with unknown type
      53              : 
      54            0 :   d.Set(name); // sets OKS data to string 'name'
      55            0 :   o->SetAttributeValue("Name", &d);
      56              : 
      57            0 :   d.Set(birthday); // sets OKS data to date 'birthday'
      58            0 :   o->SetAttributeValue("Birthday", &d);
      59              : 
      60            0 :   d.Set(familySituation);      // sets OKS data to 'familySituation'
      61            0 :   d.type = OksData::enum_type; // sets OKS data type to enumeration
      62            0 :   o->SetAttributeValue("Family_Situation", &d);
      63            0 : }
      64              : 
      65              : //
      66              : // This function prints an instance of class 'Person'
      67              : //
      68              : 
      69              : void
      70            0 : printPerson(const OksObject* o // OKS object describing person
      71              : )
      72              : {
      73            0 :   OksData* name(o->GetAttributeValue("Name"));               // is used to store 'Name'
      74            0 :   OksData* birthday(o->GetAttributeValue("Birthday"));       // is used to store 'Birthday'
      75            0 :   OksData* family(o->GetAttributeValue("Family_Situation")); // is used to store 'Family_Situation'
      76              : 
      77            0 :   std::cout << "Object " << o
      78              :             << " \n"
      79            0 :                " Name: "
      80            0 :             << *name
      81              :             << " \n"
      82            0 :                " Birthday: \'"
      83            0 :             << *birthday
      84              :             << "\" \n"
      85            0 :                " Family_Situation: "
      86            0 :             << *family << std::endl;
      87            0 : }
      88              : 
      89              : //
      90              : // This function sets attribute values of class 'Employee'
      91              : //
      92              : 
      93              : void
      94            0 : setEmployeeValues(OksObject* o,                    // OKS object that describes employee
      95              :                   const char* name,                // new employee name
      96              :                   boost::gregorian::date birthday, // new employee birthday
      97              :                   const char* familySituation,     // new employee family situation
      98              :                   uint32_t salary                  // new employee salary situation
      99              : )
     100              : {
     101              :   // we can use setPersonValues() because 'Employee' class
     102              :   // derived from 'Person' class
     103              : 
     104            0 :   setPersonValues(o, name, birthday, familySituation);
     105              : 
     106            0 :   OksData d(salary); // creates OKS data with ulong 'salary'
     107            0 :   o->SetAttributeValue("Salary", &d);
     108            0 : }
     109              : 
     110              : //
     111              : // This function prints an instance of class 'Employee'
     112              : //
     113              : 
     114              : void
     115            0 : printEmployee(const OksObject* o // OKS object that describes employee
     116              : )
     117              : {
     118              :   // we can use printPerson() because 'Employee' class
     119              :   // is derived from 'Person' class
     120              : 
     121            0 :   printPerson(o);
     122              : 
     123            0 :   OksData *department(o->GetRelationshipValue("Works at")), // is used to store 'Works at'
     124            0 :     *salary(o->GetAttributeValue("Salary"));                // is used to store 'salary'
     125              : 
     126            0 :   std::cout << " Salary: " << *salary
     127              :             << " \n"
     128              :                " Works at: \""
     129            0 :             << department->data.OBJECT->GetId() << "\"\n";
     130            0 : }
     131              : 
     132              : //
     133              : // This function sets attribute values of class 'Department'
     134              : //
     135              : 
     136              : void
     137            0 : setDepartmentValues(OksObject* o,    // OKS object that describes department
     138              :                     const char* name // new department name
     139              : )
     140              : {
     141            0 :   OksData d(name); // creates OKS data with string 'name'
     142              : 
     143            0 :   o->SetAttributeValue("Name", &d);
     144            0 : }
     145              : 
     146              : //
     147              : // This function prints an instance of class 'Department'
     148              : //
     149              : 
     150              : void
     151            0 : printDepartment(const OksObject* o // OKS object that describes department
     152              : )
     153              : {
     154            0 :   OksData *name(o->GetAttributeValue("Name")), // is used to store 'Staff'
     155            0 :     *staff(o->GetRelationshipValue("Staff"));  // is used to store 'Name'
     156              : 
     157            0 :   std::cout << "Object " << o
     158              :             << "\n"
     159            0 :                " Name: "
     160            0 :             << *name
     161              :             << " \n"
     162            0 :                " Staff: \""
     163            0 :             << *staff << "\"\n";
     164            0 : }
     165              : 
     166              : int
     167            0 : main(int argc, char** argv)
     168              : {
     169            0 :   const char* schema_file = "/tmp/tutorial.oks"; // default schema file
     170            0 :   const char* data_file = "/tmp/tutorial.okd";   // default data file
     171              : 
     172            0 :   if (argc > 1 &&
     173            0 :       (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-help") || !strcmp(argv[1], "--h") || !strcmp(argv[1], "-h"))) {
     174            0 :     std::cout << "Usage: " << argv[0] << " [new_schema new_data]\n";
     175            0 :     return 0;
     176              :   }
     177              : 
     178            0 :   if (argc == 3) {
     179            0 :     schema_file = argv[1];
     180            0 :     data_file = argv[2];
     181              :   }
     182              : 
     183              :   // Creates OKS kernel
     184              : 
     185            0 :   std::cout << "[OKS TUTORIAL]: Creating OKS kernel...\n";
     186              : 
     187            0 :   OksKernel kernel(false, false, false, false);
     188              : 
     189            0 :   std::cout << "[OKS TUTORIAL]: Done creating OKS kernel\n\n";
     190              : 
     191            0 :   try {
     192              : 
     193              :     // Creates new schema file and tests return status
     194              : 
     195            0 :     std::cout << "[OKS TUTORIAL]: Creating new schema file...\n";
     196              : 
     197            0 :     OksFile* schema_h = kernel.new_schema(schema_file);
     198              : 
     199            0 :     std::cout << "[OKS TUTORIAL]: Done creating new schema file...\n\n"
     200              :                  "[OKS TUTORIAL]: Define database class schema...\n\n"
     201              :                  "  **********        ************     1..1 **************\n"
     202              :                  "  * Person *<|------* Employee *--------<>* Department *\n"
     203            0 :                  "  **********        ************ 0..N     **************\n\n";
     204              : 
     205              :     // Creates class Person with three attributes "Name", "Birthday" and "Family_Situation"
     206              : 
     207            0 :     OksClass* Person = new OksClass("Person", "It is a class to describe a person", false, &kernel);
     208              : 
     209            0 :     Person->add(new OksAttribute(
     210            0 :       "Name", OksAttribute::string_type, false, "", "Unknown", "A string to describe person name", true));
     211              : 
     212            0 :     OksAttribute* PersonBirthday = new OksAttribute(
     213            0 :       "Birthday", OksAttribute::date_type, false, "", "2009/01/01", "A date to describe person birthday", true);
     214              : 
     215            0 :     Person->add(PersonBirthday);
     216              : 
     217            0 :     Person->add(new OksAttribute("Family_Situation",
     218              :                                  OksAttribute::enum_type,
     219              :                                  false,
     220              :                                  "Single,Married,Widow(er)",
     221              :                                  "Single",
     222              :                                  "A enumeration to describe a person family state",
     223            0 :                                  true));
     224              : 
     225              :     // Creates class Person with superclass Person, add "Salary" attribute and "Works at" relationship
     226              : 
     227            0 :     OksClass* Employee = new OksClass("Employee", "It is a class to describe an employee", false, &kernel);
     228              : 
     229            0 :     OksAttribute* EmployeeSalary = new OksAttribute(
     230            0 :       "Salary", OksAttribute::u32_int_type, false, "", "1000", "An integer to describe employee salary", false);
     231              : 
     232            0 :     OksRelationship* WorksAt = new OksRelationship("Works at",
     233              :                                                    "Department",
     234              :                                                    OksRelationship::One,
     235              :                                                    OksRelationship::One,
     236              :                                                    false,
     237              :                                                    false,
     238              :                                                    false,
     239            0 :                                                    "A employee works at one and only one department");
     240              : 
     241            0 :     Employee->add_super_class("Person");
     242            0 :     Employee->add(EmployeeSalary);
     243            0 :     Employee->add(WorksAt);
     244              : 
     245              :     // Creates class Department with one attribute and one relationship
     246              : 
     247            0 :     OksClass* Department = new OksClass("Department", "It is a class to describe a department", false, &kernel);
     248              : 
     249            0 :     OksAttribute* DepartmentName = new OksAttribute(
     250            0 :       "Name", OksAttribute::string_type, false, "", "Unknown", "A string to describe department name", true);
     251              : 
     252            0 :     OksRelationship* DepartmentStaff = new OksRelationship("Staff",
     253              :                                                            "Employee",
     254              :                                                            OksRelationship::Zero,
     255              :                                                            OksRelationship::Many,
     256              :                                                            true,
     257              :                                                            true,
     258              :                                                            true,
     259            0 :                                                            "A department has zero or many employess");
     260              : 
     261            0 :     Department->add(DepartmentName);
     262            0 :     Department->add(DepartmentStaff);
     263              : 
     264              :     // Saves created schema file
     265              : 
     266            0 :     std::cout << "[OKS TUTORIAL]: Saves created OKS schema file...\n";
     267              : 
     268            0 :     kernel.save_schema(schema_h);
     269              : 
     270              :     // Creates new data file and tests return status
     271              : 
     272            0 :     std::cout << "[OKS TUTORIAL]: Creating new data file...\n";
     273              : 
     274            0 :     OksFile* data_h = kernel.new_data(data_file, "OKS TUTORIAL DATA FILE");
     275              : 
     276            0 :     data_h->add_include_file(schema_file);
     277              : 
     278              :     // Creates instances of the classes
     279              : 
     280            0 :     OksObject* person1 = new OksObject(Person, "peter");
     281            0 :     OksObject* person2 = new OksObject(Person, "mick");
     282            0 :     OksObject* person3 = new OksObject(Person, "baby");
     283            0 :     OksObject* employee1 = new OksObject(Employee, "alexander");
     284            0 :     OksObject* employee2 = new OksObject(Employee, "michel");
     285            0 :     OksObject* employee3 = new OksObject(Employee, "maria");
     286            0 :     OksObject* department1 = new OksObject(Department, "IT");
     287            0 :     OksObject* department2 = new OksObject(Department, "EP");
     288              : 
     289              :     // Sets attribute values for instances of class 'Person'
     290              : 
     291            0 :     setPersonValues(person1, "Peter", boost::gregorian::from_string("1960/02/01"), "Married");
     292            0 :     setPersonValues(person2, "Mick", boost::gregorian::from_string("1956-09-01"), "Single");
     293            0 :     setPersonValues(person3, "Julia", boost::gregorian::from_string("2000-May-25"), "Single");
     294              : 
     295              :     // Sets attribute values for instances of class 'Employee'
     296              : 
     297            0 :     setEmployeeValues(employee1, "Alexander", boost::gregorian::from_string("1972/05/12"), "Single", 3540);
     298            0 :     setEmployeeValues(employee2, "Michel", boost::gregorian::from_string("1963/01/28"), "Married", 4950);
     299            0 :     setEmployeeValues(employee3, "Maria", boost::gregorian::from_string("1951/08/18"), "Widow(er)", 4020);
     300              : 
     301              :     // Sets attribute values for instance of class 'Department'
     302              : 
     303            0 :     setDepartmentValues(department1, "IT Department");
     304            0 :     setDepartmentValues(department2, "EP Department");
     305              : 
     306              :     // Sets relationships
     307              : 
     308            0 :     department1->AddRelationshipValue("Staff", employee1);
     309            0 :     department1->AddRelationshipValue("Staff", employee2);
     310            0 :     department2->AddRelationshipValue("Staff", employee3);
     311            0 :     employee1->SetRelationshipValue("Works at", department1);
     312            0 :     employee2->SetRelationshipValue("Works at", department1);
     313            0 :     employee3->SetRelationshipValue("Works at", department2);
     314              : 
     315              :     // Print out database contents
     316              : 
     317            0 :     std::cout << "\n[OKS TUTORIAL]: Database contains the following data:\n";
     318              : 
     319            0 :     printPerson(person1);
     320            0 :     printPerson(person2);
     321            0 :     printPerson(person3);
     322            0 :     printEmployee(employee1);
     323            0 :     printEmployee(employee2);
     324            0 :     printEmployee(employee3);
     325            0 :     printDepartment(department1);
     326            0 :     printDepartment(department2);
     327              : 
     328              :     // Saves created data file
     329              : 
     330            0 :     std::cout << "\n[OKS TUTORIAL]: Saves created OKS data file...\n";
     331              : 
     332            0 :     kernel.save_data(data_h);
     333              : 
     334            0 :     std::cout << "[OKS TUTORIAL]: Done with saving created OKS data file\n";
     335              : 
     336              :     // **********************************************************************
     337              :     //   ***** At this moment the database has been created and saved *****
     338              :     // **********************************************************************
     339              : 
     340            0 :     std::cout << "\n[OKS TUTORIAL]: Start database querying tests\n\n";
     341              : 
     342              :     // This is a test for OksComparator and OksQuery
     343              : 
     344            0 :     {
     345            0 :       std::cout << "[QUERY]: Start simple database querying...\n";
     346              : 
     347              :       // Looking for persons were born after 01 January 1960
     348              : 
     349            0 :       boost::gregorian::date aDate(boost::gregorian::from_string("1960/01/01")); // query date
     350            0 :       OksQuery query(true, new OksComparator(PersonBirthday, new OksData(aDate), OksQuery::greater_cmp));
     351              : 
     352              :       // executes query
     353              : 
     354            0 :       std::cout << "[QUERY]: Looking for persons were born after " << aDate << " ...\n\n";
     355              : 
     356            0 :       OksObject::List* queryResult = Person->execute_query(&query);
     357              : 
     358              :       // builds iterator over results if something was found
     359              : 
     360            0 :       if (queryResult) {
     361            0 :         std::cout << "[QUERY]: Query \'" << query << "\'\n  founds the following objects in class \'"
     362            0 :                   << Person->get_name() << "\' and subclasses:\n";
     363              : 
     364            0 :         for (OksObject::List::iterator i = queryResult->begin(); i != queryResult->end(); ++i) {
     365            0 :           OksObject* o = *i;
     366            0 :           OksData* d(o->GetAttributeValue("Birthday"));
     367            0 :           std::cout << "   - " << o << " was born " << *d << std::endl;
     368              :         }
     369              : 
     370              :         // free list: we do not need it anymore
     371              : 
     372            0 :         delete queryResult;
     373              :       }
     374              : 
     375            0 :       std::cout << "[QUERY]: Done with simple database querying\n\n";
     376            0 :     }
     377              : 
     378            0 :     {
     379            0 :       std::cout << "[QUERY]: Start database querying with logical function...\n";
     380              : 
     381              :       // Looking for persons were born after 01 January 1960
     382              :       // and before 01 January 1970
     383              : 
     384            0 :       boost::gregorian::date lowDate(boost::gregorian::from_string("1960/01/01"));  // low date
     385            0 :       boost::gregorian::date highDate(boost::gregorian::from_string("1970/01/01")); // high date
     386              : 
     387            0 :       OksAndExpression* andExpression = new OksAndExpression();
     388              : 
     389            0 :       andExpression->add(new OksComparator(PersonBirthday, new OksData(lowDate), OksQuery::greater_cmp));
     390            0 :       andExpression->add(new OksComparator(PersonBirthday, new OksData(highDate), OksQuery::less_cmp));
     391              : 
     392            0 :       OksQuery query(true, andExpression);
     393              : 
     394              :       // executes query
     395              : 
     396            0 :       std::cout << "[QUERY]: Looking for persons were born between " << lowDate << " and " << highDate << " ...\n\n";
     397              : 
     398            0 :       OksObject::List* queryResult = Person->execute_query(&query);
     399              : 
     400              :       // builds iterator over results if something was found
     401              : 
     402            0 :       if (queryResult) {
     403            0 :         std::cout << "[QUERY]: Query \'" << query << "\'\n  founds the following objects in class \'"
     404            0 :                   << Person->get_name() << "\' and subclasses:\n";
     405              : 
     406            0 :         for (OksObject::List::iterator i = queryResult->begin(); i != queryResult->end(); ++i) {
     407            0 :           OksObject* o = *i;
     408            0 :           OksData* d(o->GetAttributeValue("Birthday"));
     409            0 :           std::cout << "   - " << o << " was born " << *d << std::endl;
     410              :         }
     411              : 
     412              :         // free list: we do not need it anymore
     413              : 
     414            0 :         delete queryResult;
     415              :       }
     416              : 
     417            0 :       std::cout << "[QUERY]: Done database querying with logical function\n\n";
     418            0 :     }
     419              : 
     420            0 :     {
     421              : 
     422            0 :       std::cout << "[QUERY]: Start database querying with relationship expression...\n";
     423              : 
     424              :       // Looking for employee were born after 01 January 1971
     425              :       // and which works at IT Department
     426              : 
     427            0 :       boost::gregorian::date aDate(boost::gregorian::from_string("1971/01/01")); // a date
     428            0 :       const char* departmentName = "IT Department";
     429              : 
     430            0 :       OksAndExpression* andExpression = new OksAndExpression();
     431              : 
     432            0 :       andExpression->add(new OksComparator(PersonBirthday, new OksData(aDate), OksQuery::greater_cmp));
     433            0 :       andExpression->add(new OksRelationshipExpression(
     434            0 :         WorksAt, new OksComparator(DepartmentName, new OksData(departmentName), OksQuery::equal_cmp)));
     435              : 
     436            0 :       OksQuery query(true, andExpression);
     437              : 
     438              :       // executes query
     439              : 
     440            0 :       std::cout << "[QUERY]: Looking for employee were born after " << aDate << " and works at department "
     441            0 :                 << departmentName << " ...\n\n";
     442              : 
     443            0 :       OksObject::List* queryResult = Employee->execute_query(&query);
     444              : 
     445              :       // builds iterator over results if something was found
     446              : 
     447            0 :       if (queryResult) {
     448            0 :         std::cout << "[QUERY]: Query \'" << query << "\'\n  founds the following objects in class \'"
     449            0 :                   << Employee->get_name() << "\' and subclasses:\n";
     450              : 
     451            0 :         for (OksObject::List::iterator i = queryResult->begin(); i != queryResult->end(); ++i) {
     452            0 :           OksObject* o = *i;
     453            0 :           OksData* d(o->GetAttributeValue("Birthday"));
     454            0 :           std::cout << "   - " << o << " was born " << *d << std::endl;
     455              :         }
     456              : 
     457              :         // free list: we do not need it anymore
     458              : 
     459            0 :         delete queryResult;
     460              :       }
     461              : 
     462            0 :       std::cout << "[QUERY]: Done database querying with relationship expression...\n";
     463            0 :     }
     464              : 
     465            0 :     std::cout << "\n[OKS TUTORIAL]: Done with database querying tests\n\n";
     466              : 
     467              :     // It is not necessary to free data or schema because all instances of OKS
     468              :     // classes are automatic C++ objects and they will deleted before last
     469              :     // close bracket `}`.
     470              : 
     471            0 :   } catch (const std::exception& ex) {
     472            0 :     std::cerr << "Caught exception:\n" << ex.what() << std::endl;
     473            0 :   }
     474              : 
     475              :   // returns success
     476              : 
     477            0 :   return 0;
     478            0 : }
        

Generated by: LCOV version 2.0-1