How do you get the list of available types of orders (e.g., drugorder)? -Burke
On Tue, Apr 24, 2012 at 9:21 PM, Darius Jazayeri <djazayeri+...@gmail.com>wrote: > On RESTWS-243 <https://tickets.openmrs.org/browse/RESTWS-243> I've > attached a patch that contains my implementation that I'm now ready to > commit. (It's what Roger was responding to in his email.) > > I'm going to hold off on committing until after tomorrow's design call in > case we have time to discuss this a bit. > > Basically what I've done is allow resources to indicate that they support > subclasses, and if they do, they'll have all appropriate > DelegatingSubclassHandlers registered with them via spring. > > The idea is that we're hiding subclasses from the consumer of the REST > API. As far as they're concerned there is a single "order" resource, which > has documents of different types (e.g. "order", "drugorder", etc.) Behind > the scenes each type is a subclass, but in REST that's not visible, rather > they're exposed as different document types. > > DelegatingSubclassHandler encapsulates the methods subclasses need to > specify for their owning resource. > > Here is the functionality that my approach supports: > > *GET order* > > - gets all orders regardless of type > - each document in the list may have different types > - the top-level resource does the db query and delegates to the > appropriate handler to convert each result > > *GET order?t=drugorder* > > - gets all orders whose type is drugorder > - the subclass handler does the db query > - In my implementation GET order?t=order (i.e. get only things that > are order stubs) is not allowed > > *GET order?patient=<uuid>* > > - gets all orders for the given patient > - each document in the list may have different types > > *GET order?patient=<uuid>&t=drugorder* > > - gets all orders for the given patient whose type is drugorder > - if the subclass handler defines a suitable method, we use it, > otherwise the top-level resource queries by patient, and manually filters > out by type > > *GET order/<uuid>* > > - returns a specific order > - representations are defined by the type, e.g. { "type": "drugorder", > "dose": "100", ... } > > *POST order* > > - creates a new order > - you must specify the type in the content, e.g. { "type": > "drugorder", "dose": "100", ... } > - allowed properties are defined by the type > > *POST order/<uuid>* > > - modifies an existing order > - you are not allowed to change the type > - allowed properties are defined by the type > > *DELETE order/<uuid>* > > - voids an order > - handled by the top-level resource, not the subclass handler > > *DELETE order/<uuid>?purge=true* > > - purges an order > - handled by the top-level resource, not the subclass handler > > @Roger, can you please phrase your counterproposal in terms of the > additional functionality that you want to expose beyond these methods? > > -Darius > > > On Mon, Apr 23, 2012 at 9:54 AM, Burke Mamlin <bmam...@regenstrief.org>wrote: > >> Roger, >> >> Could you provide some concrete examples? >> >> -Burke >> >> >> On Mon, Apr 23, 2012 at 8:07 AM, Friedman, Roger (CDC/CGH/DGHA) (CTR) < >> r...@cdc.gov> wrote: >> >>> 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.**** >>> ------------------------------ >>> Click here to >>> unsubscribe<lists...@listserv.iupui.edu?body=SIGNOFF%20openmrs-devel-l>from >>> OpenMRS Developers' mailing list >> >> >> ------------------------------ >> Click here to >> unsubscribe<lists...@listserv.iupui.edu?body=SIGNOFF%20openmrs-devel-l>from >> OpenMRS Developers' mailing list >> > > ------------------------------ > Click here to > unsubscribe<lists...@listserv.iupui.edu?body=SIGNOFF%20openmrs-devel-l>from > OpenMRS Developers' mailing list > _________________________________________ To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to lists...@listserv.iupui.edu with "SIGNOFF openmrs-devel-l" in the body (not the subject) of your e-mail. [mailto:lists...@listserv.iupui.edu?body=SIGNOFF%20openmrs-devel-l]