Using Dynamic Dictionaries
In the following example, a dynamic dictionary performs an object sort based on member attributes. The publications property is a collection of Publications. This example shows the use of the reimplemented Dictionary class startKeyGeq method to start the iteration at a specific point and demonstrates passing a variable list of key parameters where the keys are not known at compile-time.
vars dynaDict : DynaDictionary; pub : Publication; iter : Iterator; begin create dynaDict transient; // set the membership of our dynamic dictionary dynaDict.setMembership(Publication); // specify the ytdSales, royalty, and descending pubDate dictionary keys dynaDict.addMemberKey("ytdSales", false, false); dynaDict.addMemberKey("royalty", false, false); // specify descending key so that most recent titles appear first dynaDict.addMemberKey("pubdate", true, false); // complete key definition dynaDict.endKeys(false); // copy publication instances into the dynamic dictionary publications.copy(dynaDict); // display all publications with more than 1000 // sales (ytd) in sorted order iter := dynaDict.createIterator; // start the iteration where ytdSales >= 1000 // since the dynadict has 3 keys we must pass // keys to the startKeyGeq method dynaDict.startKeyGeq(1000, null, null, iter); while iter.next(pub) do write pub.name & " " & pub.ytdSales.String & pub.royalty.String & " " & pub.pubdate.String; endwhile; epilog // ensure we delete transients delete iter; delete dynaDict; end;
The following example shows the use of a dynamic dictionary that orders employees by age and length of service. These key values are returned by the getAge and getLengthOfService methods in the Employee class. As the key values are not properties, the dynamic dictionary cannot be defined using member keys and can only be defined using external keys.
vars dyna : DynaDictionary; emp : Employee; root : Root; iter : Iterator; begin create dyna transient; dyna.setMembership(Employee); dyna.addExternalKey(TimeStampInterval,8,false,false); // age dyna.addExternalKey(TimeStampInterval,8,false,false); // length service dyna.endKeys(false); // no duplicates root := Root.firstInstance; foreach emp in root.allEmployeesByName do dyna.putAtKey(emp.getAge, emp.getLengthOfService, emp); endforeach; iter := dyna.createIterator(); while iter.next(emp) do write emp.name & Tab & emp.dob.shortFormat; endwhile; epilog delete dyna; delete iter; end;
The following examples demonstrate the use of a dynamic dictionary in an application-specific query where a suitable dictionary type is not available in the object model. These examples show the use of a key path specification and the bracket ([ ]) substring operators to perform a dictionary lookup and use the model Department, Employee, and DepartmentSet (a set of Department) classes, with the following partial definitions.
Employee ( referenceDefinitions department: Department explicitInverse, readOnly; ) Department ( referenceDefinitions manager: Employee explicitInverse, readOnly; )
The following AQController class is a query controller, which has a singleton transient instance at run time. This class defines the managers exclusive property of type DynaDictionary.
AQController ( referenceDefinitions managers : DynaDictionary implicitMemberInverse, protected; jadeMethodDefinitions // public interface operations getManagerByDeptName(deptName: String): Manager; // implementation method loadManagers(departments: DepartmentSet) protected; )
The following method is called when an AQController instance is initialized and sets up and then populates the managers dynamic dictionary. You could use a notification mechanism to ensure that the managers dictionary is kept current when departments are added or deleted or managers are changed.
AQController::loadManagers loadManagers(departments: DepartmentSet) protected; vars dept : Department; begin // set the membership of our dynamic dictionary managers.setMembership(Employee); // the single key is the keypath: department.name managers.addMemberKey("department.name", false, false); // end key specification, and do not allow duplicates as the // model does not allow two departments with the same name managers.endKeys(false); foreach dept in departments do managers.add(dept.manager); endforeach; end;
The following method looks up the managers dynamic dictionary to find the manager by department name.
AQController::getManagerByDeptName getManagerByDeptName(deptName: String): Manager; begin return managers[deptName].Manager; end;