root/trunk/grails-app/controllers/RestController.groovy @ 901

Revision 901, 9.5 KB (checked in by jahn, 4 years ago)

Added and tested new Rest methods in accordance with specs.
Tested most of them. User related information is not integrated
yet. Furthermore, added new convention for refering to TemplateEntities?
by REST. For the time being, the old conventions and the new
conventions are supported in parallel. However, this should change
soon. Thus, currently externalAssayID, code, and externdaSampleID
are supported, as are assayToken, studyToken, sampleToken.

Line 
1/**
2 * RestControler
3 *
4 * This controler provides a REST service.
5 * The names of the RESET resources are the same as the names of this
6 * controller's actions. E.g., the resources called getStudies simply
7 * corresponds to the action getStudies. Some of the resources are parameterized.
8 * The parameters are passed as parameters in the url and are available in the
9 * params respecting Grails' conventions. In this file, we adher to the javadoc 
10 * convention for describing parameters ("@param"), but actually we mean
11 * key-value pairs in the params object of each Grails action we comment on.
12 *
13 * @author      Jahn-Takeshi Saito
14 * @since       20100601
15 *
16 */
17
18import dbnp.studycapturing.Study
19import dbnp.studycapturing.Assay
20import grails.converters.*
21import nl.metabolomicscentre.dsp.http.BasicAuthentication
22
23
24class RestController {
25
26
27
28       /**************************************************/
29      /** Rest resources for Simple Assay Module (SAM) **/
30     /**************************************************/
31
32        def authService
33        def beforeInterceptor = [action:this.&auth,except:["isUser"]]
34        def credentials
35        def requestUser
36
37        /**
38         * Authorization closure, which is run before executing any of the REST resource actions
39         * It fetches a username/password combination from basic HTTP authentication and checks whether
40         * that is an active (nimble) account
41         * @return
42         */
43        private def auth() {
44
45            credentials = BasicAuthentication.credentialsFromRequest(request)
46                requestUser = authService.authUser(credentials.u,credentials.p)
47                if(!requestUser) {
48                    response.sendError(403)
49                return false
50            }
51                else {
52                        return true
53                }
54        }
55
56        /**
57        * REST resource for data modules.
58        * Username and password should be supplied via HTTP Basic Authentication.
59        * Determines whether the given user/password combination is a valid GSCF account.
60        *
61        * @return bool {"authenticated":true} when user/password is a valid GSCF account, {"authenticated":false} otherwise.
62        */
63        def isUser= {
64                boolean isUser
65                credentials = BasicAuthentication.credentialsFromRequest(request)
66                def reqUser = authService.authUser(credentials.u,credentials.p)
67                if (reqUser) {
68                        isUser = true
69                }
70                else {
71                        isUser = false
72                }
73                def reply = ['authenticated':isUser]
74                render reply as JSON
75        }
76
77        /**
78        * REST resource for data modules.
79        * Username and password should be supplied via HTTP Basic Authentication.
80        * Provide a list of all studies owned by the supplied user.
81        *
82        * @return JSON object list containing 'externalStudyID', and 'name' (title) for each study
83        */
84        def getStudies = {
85                List studies = []
86                def user = params.user
87                Study.findAllByOwner(requestUser).each { study ->
88                        studies.push( [ 'externalStudyID': study.code, 'name':study.title, 'studyToken':study.code ] )
89                }
90                render studies as JSON
91        }
92
93
94        /**
95        * REST resource for data modules.
96        * Username and password should be supplied via HTTP Basic Authentication.
97        * Provide a list of all subjects belonging to a study.
98        *
99        * @param externalStudyID String The external study id (code) of the target GSCF Study object
100        * @return JSON object list of subject names
101        */
102        def getSubjects = {
103                List subjects = []
104                if( params.externalStudyID ) {
105                        def id = params.externalStudyID
106                        def study = Study.find( "from Study as s where s.code=?", [id])
107                        if(study) study.subjects.each { subjects.push it.name }
108                }
109                render subjects as JSON
110        }
111
112
113        /**
114        * REST resource for data modules.
115        * Username and password should be supplied via HTTP Basic Authentication.
116        * Provide a list of all assays for a given study
117        *
118        * Example call of the getAssays REST resource:
119        * http://localhost:8080/gscf/rest/getAssays?externalStudyID=PPSH&moduleURL=http://localhost:8182/sam
120        *
121        * @param externalStudyID String The external study id (code) of the target GSCF Study object
122        * @param moduleURL String The base URL of the calling dbNP module
123        * @return list of assays in the study as JSON object list, filtered to only contain assays
124        *         for the specified module, with 'externalAssayID' and 'name' for each assay
125        */
126        def getAssays = {
127                List assays = []
128                if( params.externalStudyID || params.studyToken ) {
129                        def id = params.studyToken ?: params.externalStudyID
130                        def study = Study.find( "from Study as s where s.code=?", [id] )
131                        if(study && study.owner == requestUser) study.assays.each{ assay ->
132                                if (assay.module.url.equals(params.moduleURL)) {
133                                def map = ['name':assay.name, 'externalAssayID':assay.externalAssayID, 'assayToken':assay.externalAssayID]
134                                        assays.push( map )
135                                }
136                        }
137                }
138                render assays as JSON
139        }
140
141
142        /**
143        * REST resource for data modules.
144        * Username and password should be supplied via HTTP Basic Authentication.
145        * Provide all samples of a given Assay. The result is an enriched list with additional information for each sample.
146        *
147        * @param externalAssayID String (externalAssayID of some Assay in GSCF)
148        * @return As a JSON object list, for each sample in that assay:
149        * @return 'name' (Sample name, which is unique)
150        * @return 'material' (Sample material)
151        * @return 'subject' (The name of the subject from which the sample was taken)
152        * @return 'event' (the name of the template of the SamplingEvent describing the sampling)
153        * @return 'startTime' (the time the sample was taken relative to the start of the study, as a string)
154        */
155        def getSamples = {
156                def items = []
157                if( params.externalAssayID ) {
158                        def assay = Assay.find( "from Assay as a where externalAssayID=?",[params.externalAssayID])
159                        assay.getSamples().each { sample ->
160                                def item = [
161                                        'name'                : sample.name,
162                                        'material'            : sample.material.name,
163                                        'subject'             : sample.parentSubject.name,
164                                        'event'               : sample.parentEvent.template.name,
165                                        'startTime'           : sample.parentEvent.getStartTimeString()
166                                ]
167                                items.push item
168                        }
169                }
170                render items as JSON
171        }
172
173
174
175
176
177        /**
178        * REST resource for dbNP modules.
179        *
180        * @param studyToken String, the external identifier of the study
181        * @return List of all fields of this study
182        * @return
183        *
184        * Example REST call (without authentication):
185    * http://localhost:8080/gscf/rest/getStudy/study?studyToken=PPSH
186    *
187        * Returns the JSON object:
188        * {"title":"NuGO PPS human study","studyToken":"PPSH","startDate":"2008-01-13T23:00:00Z",
189        * "Description":"Human study performed at RRI; centres involved: RRI, IFR, TUM, Maastricht U.",
190        * "Objectives":null,"Consortium":null,"Cohort name":null,"Lab id":null,"Institute":null,
191        * "Study protocol":null}
192        */
193        def getStudy = {
194                def items = [:]
195                if( params.studyToken ) {
196                        def study = Study.find( "from Study as s where code=?",[params.studyToken])
197                        study.giveFields().each { field ->
198                                def name = field.name
199                                def value = study.getFieldValue( name )
200                                if(name=="code") { name = "studyToken" }
201                                items[name] = value
202                        }
203        }
204                render items as JSON
205        }
206
207
208
209        /**
210        * REST resource for dbNP modules.
211        *
212        * @param assayToken String, the external identifier of the study
213        * @return List of all fields of this assay
214        *
215        * Example REST call (without authentication):
216    * http://localhost:8080/gscf/rest/getAssay/assay?assayToken=PPS3_SAM
217    *
218        * Returns the JSON object: {"name":"Lipid profiling","module":{"class":"dbnp.studycapturing.AssayModule","id":1,
219        * "name":"SAM module for clinical data","platform":"clinical measurements","url":"http://sam.nmcdsp.org"},
220        * "assayToken":"PPS3_SAM","Description":null}
221        */
222        def getAssay = {
223                def items = [:]
224                if( params.assayToken ) {
225                        def assay = Assay.find( "from Assay as a where externalAssayID=?",[params.assayToken])
226                        assay.giveFields().each { field ->
227                                def name = field.name
228                                def value = assay.getFieldValue( name )
229                                if(name=="externalAssayID") { name = "assayToken" }
230                                items[name] = value
231                        }
232        }
233                render items as JSON
234        }
235
236
237
238        /**
239        * REST resource for data modules.
240        * Username and password should be supplied via HTTP Basic Authentication.
241        * One specific sample of a given Assay.
242        *
243        * @param externalAssayID String (externalAssayID of some Assay in GSCF)
244        * @return As a JSON object list, for each sample in that assay:
245        * @return 'name' (Sample name, which is unique)
246        * @return 'material' (Sample material)
247        * @return 'subject' (The name of the subject from which the sample was taken)
248        * @return 'event' (the name of the template of the SamplingEvent describing the sampling)
249        * @return 'startTime' (the time the sample was taken relative to the start of the study, as a string)
250        *
251        * Example REST call (without authentication):
252    * http://localhost:8080/gscf/rest/getSample/sam?assayToken=PPS3_SAM&sampleToken=A30_B
253    *
254        * Returns the JSON object:
255        * {"subject":"A30","event":"Liver extraction","startTime":"1 week, 1 hour",
256        * "sampleToken":"A30_B","material":{"class":"dbnp.data.Term","id":6,"accession":"BTO:0000131",
257        * "name":"blood plasma","ontology":{"class":"Ontology","id":2}},"Remarks":null,
258        * "Text on vial":"T70.91709057820039","Sample measured volume":null}
259        */
260        def getSample = {
261                def items = [:]
262                if( params.assayToken && params.sampleToken ) {
263                        def assay = Assay.find( "from Assay as a where externalAssayID=?",[params.assayToken])
264                        assay.getSamples().each { sample ->
265                                if( sample.name == params.sampleToken ) {
266                                        items = [
267                                                'subject'             : sample.parentSubject.name,
268                                                'event'               : sample.parentEvent.template.name,
269                                                'startTime'           : sample.parentEvent.getStartTimeString()
270                                        ]
271                                        sample.giveFields().each { field ->
272                                                def name = field.name
273                                                def value = sample.getFieldValue( name )
274                                                if(name=="name") { name = "sampleToken" }
275                                                items[name] = value
276                        }
277                                }
278                        }
279                }
280                render items as JSON
281        }
282}
Note: See TracBrowser for help on using the browser.