[Nodal-j-devel] Getter/Setter interfaces
Status: Pre-Alpha
Brought to you by:
leei
From: Lee I. <le...@te...> - 2002-05-30 04:24:04
|
A note to explain the organizing principle behind the Getter/Setter interfaces. Requirements: o A structure for organizing access to elements of the collections that the Node data types represent. o Must minimize need to check permissions for particular data access or modification checks, since these checks may be expensive (client-server roundtrip?) o Wish to remove unnecessary type conversions, and in particular to eliminate the need to convert to/from Object wrappers for fundamental data types simply in order to pass arbitrarily typed arguments. Solution: Getter and Setter interfaces as mediators of the data access and modification operations. A Getter is an interface that allows read access to data of a particular type. The generic Getter interface converts from that type to an Object via the get() method and provides a String conversion operator via the getString() method. interface Getter { Object get(); String getString(); }; Thus, a data access primitive will return a Getter object as a promise that the user will be able to obtain the current value at any later point in time by simply calling the get() method. Moreover, the permission check for access is performed when the Getter is constructed, thus obviating the need to explicitly check permissions every time the get() method is called. Finally, the Getter can be extended by making it an Observable object, thus allowing a client application to register its interest in changes to the value of the Getter and to be notified of these changes at any later time. An example interface (from NODAL): interface Content { Type type(); int size(); Enumeration properties(); Getter value(Object property); }; interface RecordContent : Content { Getter field (Name fieldName); }; And a usage example: void walkContent (Node n) { Content content = n.content(); Enumeration e = content.properties(); while (e.hasMoreElements()) { Object property = e.nextElement(); Object value = content.value(property).get(); } } N.B. In C++ it is natural to present the Getter interface as a smart pointer type, with the dereference operator*() analogous to the get() method. As far as the optimization of accesses and reduction of type conversion, it is possible, and very useful, to be able to extend the interface by providing type-specific Getter interfaces that allow direct access to the fundamental data types enclosed by the Getter. For example: interface CharGetter : Getter { char getChar (); }; In addition, we can cascade some of these interfaces whenever data conversions would happen automatically w/o loss of precision. For example: interface ByteGetter : Getter { byte getByte(); }; interface ShortGetter : ByteGetter { short getShort(); }; interface IntegerGetter : ShortGetter { int getInt(); }; interface FloatGetter : Getter { float getFloat(); }; interface DoubleGetter : FloatGetter { double getDouble(); }; Now, data access methods can create and return any of these type-specific Getter objects while still conforming to a method signature that specifies it should return a Getter. The client can then, either through direct knowledge or tentatively check for the availability of the efficient, direct interfaces in appropriate cases. For modifying values, there is an analogous Setter interface: interface Setter : Getter { Object set (Object value); Object setString (String value); }; Thus a data modifying primitive will return a Setter object that encapsulates the ability to modify a given value in a given way at some later time. The data object will thus check permissions when the Setter is requested and can potentially forgo such checks when the set() method is later called. Note that the Setter inherits from Getter. This is based on the assumption, inherent in the NODAL security/privacy system, that write/modifcation access is never granted w/o read access. In virtually all cases it makes sense to treat these access primitives in this hierarchical fashion and it makes virtually every aspect of the system easier to manipulate by making this assumption. (Of course it is possible to reconsider this conclusion). Finally it is possible, and appropriate, to subclass the Setter interface in exactly the same type-specific way as we did for the Getter interface, thus providing us with a means to bypass the Object wrap/unwrap process inherent in the generic set() interface. An example: interface NodeEditor : NodeContent { Setter setProperty (Object property); }; |