LCOV - code coverage report
Current view: top level - oksutils/apps - oks_tutorial.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 194 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 7 0

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

Generated by: LCOV version 2.0-1