Give us contact

Do you prefer to ask us directly?

Call us +420 605 203 938 (the Czech Republic)

or use this contacts

AyMINE

Related links


FI - Finance Management

Object inheritance

Inheritance of the persistent objects

About inheritance

The AyMINE objects support inheritance. The inheritance is applied for all parts of the object – attributes, view definitions as well as orchestration methods. The descendant object can even define its own attributes stored in the separate table. Object can have only single direct parent (multiple-parent inheritance is not supported).

An object that is a descendant of another object should have extension defined in the object about definition:

{ 
   // About the file with object definition
   "about": 
   {
      "version":1,
      "module":"<module>",
      "name":"<descendant object name>"},  

   // Object definition
   "data": {

      // About the object
      "about": {  
         "extends":"<parent object name>",
         "name":"<object name>",
         . . . 
         "type":"<descendant object type>", 
         "classID":"<descendant object short id>",
         "short":"<optional shortage>",
         "icon":"<descendant object icon>",
         "groups":["extending parent object list of groups"],
         "langModules": [ "extending parent object list of translation string resources" ]
      }
   },
   
   // Object database definition
   "tableSQL": {
      "module":"<descendant module – could be different from parent module",
      "extendingTable":"name of the table with descendant attributes"
      . . . 
   },

}   

Object distinctions in database

It is expected that an object that supports inheritance, has defined attribute systemObject:

"systemObject":{
   "type":"string",        // name of the object
   "lenght":32,            // maximal supported object name lenght
   "required":true,        // system object should always be defined
   "default":"@fAttr.this" // default ways how to fill the object name
},

It is strongly recommended to follow this rule and always created the systemObject attribute. The application is tested only with inherited objects that follow this rule. Some of the default methods defined by persistentObject class trust on that. However, this is not required and objects can use inheritance even without that but all methods should be properly tested!

It is also stronly recommended not to use the systemObject attribute for anything else.

How is the object inherited

The complete master object definition is inherited to the descendant object. The descendant object could change definitions or add new parts in the same way as is used in other programming languages (TypeScript, C++, PHP etc.).

Attribute inheritance

Abstract master object could define attributes and descendant can complete or change its definition:

Master object
The abstract master object has attributes:

"attributes": {
   // systemObject attribute that 
   "systemObject":{"type":"string", "required":true, "default":"@fAttr.this"},
   . . .
}

Descendant object
The descendant adds its own attrbitutes:

"attributes": {
   // redefine the master object attributes
   "systemType":{
      // Descendant uses its own counter for system type attribute
      "type":"enum",
      "enum":"tsk/problemSystemType", 
      "required":true 
   },
   // Other field changes
   "priority":{"type":"enum", "required":true, "enum":"sys/priority"}
}

Descendant iherits all master attributes and can modify their definition

Extending table for descendant object

Descendant object can define its own attributes and store them in a slave table. The slave table definition should fulfil the rules:

  • Name of the slave table is not limitied. the Recommended name is <master object table name>_<slave object name>. Example: tskInfItem_problem
  • Name of the ID field in the slave table should be the same as the ID name of the field in the master table
  • Slave table name is defined by the object field definition data->tableSQL->extendingTable.
  • Records in the slave table are auto-deleted by database constraint linked with the master table
  • Attributes of the slave objects are defined in the slave object with "source":"objExtension"
  • Records on the slave table are not always created. They are created only if user edits some of the additional fields. When the slave record is created it is never deleted by application, but should be deleted by database through the cascade constraint.
  • Application supports only single descendant slave table. More complex inheritance is not supported. However, objects can be inherited with more than single parent: <abstract parent> -> <specific object> -> <specific object variant>

Descendant object example

Problem is descendant of the abstract parent object AbstractInfItem. Parent object is stored in the tskInfItem table with tskInfItemID ID field

Descendant table and view definition

The descendant object is defined:

CREATE OR REPLACE TABLE tskInfItem_problem (
   -- primary key has the same name as in the master table
   -- slave tables never have its own id but always shares id from master table
   tskInfItemID BIGINT UNSIGNED NOT NULL, 
      PRIMARY KEY (tskInfItemID),
      -- constraint deletes slave record with master record
      -- application does not do that and trust on the database 
      CONSTRAINT fk_tskInfItem_problem_master 
         FOREIGN KEY (tskInfItemID) 
         REFERENCES tskInfItem(tskInfItemID) 
         ON DELETE CASCADE,
   -- fields of the descendant object
   reportedByName varchar(32) comment 'user or other subject that reported the problem',
   reportedByID bigint unsigned null comment 'ID for reportedBy' 
) comment 'Additional fields for object tskProblem';

The descendant object also needs a database view for list and detail application views:

create or replace view tskwProblemS as select
   ii.*, 
   -- add extended fields indcluding their definition
	ip.reportedByName,
	ip.reportedByID,
   -- add field with description of the linked object
	objDesc(ip.reportedByName,ip.reportedbyID) as reportedbyIDDesc
from
   tskwInfItemDetailS ii
      left outer join tskInfItem_problem ip on ip.tskInfItemID = ii.tskInfItemID;

The descendant object definition

{ 
"about": { . . . },  
"data": {

"about": {  "extends":"tskAbstractInfItem",
   "name":"tskProblem",
   . . . 
   // Adds its own list of translation string
   "langModules": [ "tsk/langs/@/problem" ]
},   

"attributes": {
   . . . 
   // New attribues defined by descendant object and stored in the slave table
   "reportedByName":{ 
      "type":"string", "length":32, 
      "source":"objExtension"   // information where attributes are stored
   },
   "reportedByID":{ 
      "type":"objectPrincipal", 
      "source":"objExtension", 
      "objAllowed":["sysUser", "crmPersonSubject"] 
   }
}

"tableSQL": {
   // Descendant object should define its module (even when is from the same module as the parent).
   "module":"tsk",
   // Name of the table where the descendant attributes are stored
   "extendingTable":"tskInfItem_problem",
   . . . 
},

"views":{
   // ***************************      Details     ****************************
   "details":{

      "default":{
         . . . 
         "serverData": {  
            // Descendant object should have defined view that combines data from both tables
            // Application does not automatically loads fields from more tables because
            // all larger object needs view anyway
            "selectFROM":"tskwProblemS"  
         }
      }
   },
} } }