AN ALTERNATIVE APPROACH TO SUBCLASS IMPLEMENTATION

In this approach, subclass resources remain resources, just are mapped via the 
superclass. Substantially all operations are delegated to the appropriate 
subclass resource. This is motivated by simplicity, validation and 
representation considerations. It is also motivated by a privilege issue I just 
realized - the people authorized to create/update a lab order are likely 
different from those allowed to create/update a drug order. I have assumed that 
the privilege of updating a parent class field in subclass record requires only 
parent class privileges

I don't believe this alternative requires much in the way of changes to 
existing code other than mappings; adding the controller and resource for each 
superclass; some changes in asRepresentation where it finds the right 
representation to use; and some changes where updates are going on to allow the 
possibility that the fields to be looked for in the request body may come from 
an object which is a parent class of the object being updated. It eliminates 
the need for the two variable lists used by Darius (although they could still 
be used if it was thought they added value). I still think it is a good idea to 
treat ActiveLists as an abstract class so that the AllergyList and the 
ProblemList appear to be two different superclasses.

All members of a class hierarchy request a mapping to 
/<superclass>?t=<subclass>. The superclass also requests a mapping to 
/<superclass>?!t. I have tried to make all the calls of /<superclass>?!t work 
the same as calls to /<superclass>?t=<superclass>, if I have missed please let 
me know.  It might be worthwhile to extend Resource to SuperclassResource to 
make the coding of the type-free calls easier.  All representations include a t 
virtual field which contains the actual subclass of the object being 
represented.

1. GET <superclass>?t=<subclass>&v=<rep>, GET <superclass>?!t

Purpose is to get all records of a particular subclass in a formatted 
representation. Spring routes this to the subclass controller. The subclass 
resource uses getAll to get a (polymorphic) list of objects. asRepresentation 
determines the class of each object and looks for the requested representation 
in that subclass resource; if it exists, it is used; if not, the parent class 
resource (if any) is searched for a representation; this continues until the t 
subclass has been searched, at which point a rep does not exist error is thrown.

2. GET <superclass>?t=<subclass>&v=<rep>&q=<search param>, GET 
<superclass>?!t&v=<rep>&q=<search param>

Purpose is to use the standard query for a subclass to get a formatted 
representation. Spring routes this to the subclass controller. The subclass 
resource uses doSearch to get a (polymorphic) list of objects. asRepresentation 
determines the class of each object and looks for the requested representation 
in that subclass resource; if it exists, it is used; if not, the parent class 
resource (if any) is searched for a representation; this continues until the t 
subclass has been searched, at which point a rep does not exist error is thrown.

3. GET <superclass>?t=<subclass>&v=<rep>&<custom search>=<search param>

Purpose is to do a custom search that is defined at some level of the class 
hierarchy.  Spring routes this to the subclass controller. The subclass 
controller creates a resource for its type and delegates the search to it. The 
resource uses service methods to do the search to produce a (polymorphic) list 
of objects. asRepresentation determines the class of each object and looks for 
the requested representation in that subclass resource; if it exists, it is 
used; if not, the parent class resource (if any) is searched for a 
representation; this continues until the t subclass has been searched, at which 
point a rep does not exist error is thrown.

4. GET <superclass>/<uuid>?!t&v=<rep>

Purpose is to get all records of a particular subclass in a formatted 
representation. Spring routes this to the superclass controller. The superclass 
resource uses getByUuid to get an object. asRepresentation determines the class 
of each object and looks for the requested representation in that subclass 
resource; if it exists, it is used; if not, the parent class resource (if any) 
is searched for a representation; this continues until the t subclass has been 
searched, at which point a rep does not exist error is thrown.

5. GET <superclass>/<uuid>?t=<subclass>&v=<rep>

Purpose is to use a representation from a parent class. Like 5, except after 
getting by Uuid, the subclass resource coerces the result to be its type. 
asRepresentation determines the class of each object and looks for the 
requested representation in that subclass resource; if it exists, it is used; 
if not, the parent class resource (if any) is searched for a representation; 
this continues until the supertype has been searched, at which point a rep does 
not exist error is thrown.

6. POST <superclass>?t=<subclass> {body}

Purpose is to create a new object of type <subclass>. The subclass resource 
creates a new object whose fields are extracted from the body (no need to know. 
The subclass resource save method uses services method to save the object; 
validation takes place in the save method.

7. POST <superclass>/<uuid>?!t {body}

Purpose is to update an object of any subclass. The type is determined and the 
operation is delegated to the resource of the actual type.

8. POST <superclass/<uuid>?t=<subclass> {body}

Purpose is to update an object using only parent-level fields. This is to avoid 
additional privileges at the actual subclass level. The type is deermined and 
the operation is delegated to the resource of the declared type. Throws an 
error if the actual type is not a subclass of the type declared.

9. DELETE <superclass>/<uuid>?!t&!purge, DELETE 
<superclass>/<uuid>?t=<subclass>&!purge

Purpose is to delete an object of any subclass. The type is determined and the 
operation is delegated to the resource of the actual type. The subclass, if 
present, must match the actual type of the resource.

10. DELETE <superclass>/<uuid>?purge&!t, DELETE <superclass>/<uuid>?purge

Purpose is to purge an object of any subclass. The type is determine and the 
operation is delegated to the resource of the actual type. The subclass, if 
present, must match the actual type of the resource.

_________________________________________

To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to 
[email protected] with "SIGNOFF openmrs-devel-l" in the  body (not 
the subject) of your e-mail.

[mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

Reply via email to