Building a Mediator

Step 4: Defining the mediator - attributes

Now we move away from the extent of the Person class, and focus instead on the individual objects in the class. Each will have an OID which is, in this example, the Employee ID from the phonebook. As we describe how to populate the attributes and relationships of each object, we'll be able to refer to the object's OID using the keyword self.

The second place we insert OQL is in the attribute definitions. The Person class has two attributes, name and salary. Let's assume that the name of each person will come from their phonebook entry. The OQL query to retrieve a name from the phonebook given an Employee ID is:

  element(
    select p.last + ", " + p.first
    from Phonebook p
    where p.ID = self
  );

For the salary attribute, let's assume that the payroll database is relational, and contains two tables (of interest), PayEmps and PayRanges. The rows of PayEmps correspond to employees, and each contains the pay range to which the employee belongs, and the employee's salary expressed as a percentage of the top salary in the pay range. The rows of PayRanges hold the maximum and minimum salaries for each pay range. An employee's salary can be calculated by multiplying the percentage from PayEmps and the maximum salary from PayRanges for the appropriate range. The OQL that expresses this query is below.

  element(
    select trunc(emp.pay_percentage * range.max_salary)
    from Payroll_PayEmps emp, Payroll_PayRanges range
    where emp.Emp_ID = self and emp.range_ID = range.ID
  );

We insert these two pieces of OQL after the corresponding attribute definitions, before the semicolon:

  classdef Person (extent People { select distinct p.ID from Phonebook p; })
  {
    attribute String name {
        element(select p.fullname from Phonebook p where p.ID = self);
    };
    attribute integer salary {
        element(
          select trunc(emp.pay_percentage * range.max_salary)
          from Payroll_PayEmps emp, Payroll_PayRanges range
          where emp.Emp_ID = self and emp.range_ID = range.ID
        );
    };

    relationship set member_of_projects
        inverse Project::team;
    relationship set manager_of_projects
        inverse Project::manager;
  }

Note that the type returned by the OQL for each attribute must match the type defined in the ODL for that attribute. This is why the element function is used - without it we would be trying to assign a collection type to the name or salary.

We have just used simple scalar types for our attributes in this example, but any type supported by ODL can be used, along with an OQL statement that returns a corresponding type. For object-valued attributes, the type returned by the OQL must match the type of elements in the extent of the class.

With the extents and attributes defined, all that remains is to define the relationships.


[Tech Docs Index]