source: trunk/src/groovy/dbnp/rest/common/CommunicationManager.groovy @ 1196

Last change on this file since 1196 was 1196, checked in by j.saito@…, 9 years ago

Streamlined CommunicationManager? and adjusted it to suit CommunicationManager? in SAM.
Removed horrible debugoutputs from SimpleQueryController?. (Is this used any longer at all??)

File size: 5.9 KB
Line 
1package dbnp.rest.common
2
3import grails.converters.JSON
4import java.net.URLEncoder
5import org.codehaus.groovy.grails.web.json.*
6
7
8/**  CommunicationManager
9 *
10 *   @author Jahn
11 *
12 *   This class manages communication between dbNP modules such as GSCF and SAM.
13 *   By communication we mean two ways of exchanging information: (1) via Rest resources,
14 *   and (2) via Grails views that a module can make available to another module.
15 *
16 *   For Rest communication this class implements a Rest client that fetches data
17 *   from other modules' Rest resources. The Rest implementation transfers data in JSON.
18 *
19 *   Note: Do not use this class directly to fetch data. Instead use your module's
20 *   rest wrapper methods. Use this module, to create these rest wrapper methods.
21 *   For instance, use dbnp.rest.sam.registerRestWrapperMethodsGSCFtoSAM to register new methods
22 *   for accessing GSCF's Rest service in SAM; your new method shoud then use this class.
23 */
24
25
26class CommunicationManager {
27
28
29    /* this should moved somewhere else */
30    /* The static URLs are set in grails-app/conf/Config.groovy */ 
31    def        static Encoding      = "UTF-8" 
32    def public static ServerURL     = "http://localhost:8182/sam"
33    def public static SAMServerURL  = "http://localhost:8182/sam"
34    def public static GSCFServerURL = "http://localhost:8080/gscf"
35    def public static DSPServerURL  = "http://localhost:8080/ncdsp"
36
37
38
39    /**
40     * Get the results of provided by a rest Rest resource.
41     *
42     * @params String resource The name of the resource, e.g. importer/pages
43     * @params Map params      A Map of parmater names and values., e.g. ['externalAssayID':12]
44     * @return String url   
45     */
46    public static Object getRestResource( RestServerURL, resource, params ) {
47                def url = getRestURL( RestServerURL, resource, params )
48                return  JSON.parse( url.newReader() )
49    }
50
51
52    /**
53     * Convenience method for constructing URLs for SAM that need parameters.
54     * Note that parameters are first convereted to strings by calling their toString() method
55     * and then Encoded to protect special characters.
56     *
57     * @params String resource The name of the resource, e.g. importer/pages
58     * @params Map params      A Map of parmater names and values., e.g. ['externalAssayID':12]
59     * @return String url   
60     */
61    public static URL getRestURL( RestServerURL, resource, params ) {
62        def url = RestServerURL + '/' + resource
63                def first = true
64                params['consumer']=ServerURL
65                params.each { name, value ->
66                        if(first) {
67                                first = false
68                                url += '/nil?' + name + "=" + URLEncoder.encode( value.toString(), Encoding )
69                        }
70                        else { 
71                                url += '&' + name + "=" + URLEncoder.encode( value.toString(), Encoding  )
72                        }
73                }
74                return new URL( url )
75    }
76
77
78
79    /**
80     * This method dynamically adds a static method to the CommunicationManager.
81     * 
82     * @params String serverURL         A rest server URL.
83     * @params String restName          The name of a rest resource on the server.     
84     * @params Map params               A list of parameter names to be passed to this resource.
85     * @return String url   
86     * 
87     * Given a rest resource at serverURL called resourceName, we register a static method
88     * for the CommunicationManager. The new method has the same name and arity as the resource.
89     * 
90     * Example: Suppopse http://localhost:8080/gscf/rest/getSamples is a Rest resource.
91     * 
92     * In our grails app, we would like to connect to this service. We want to have a
93     * method getSamples() that fetches the result from the service. We do this by calling
94     * 
95     *          CommunicationManager.addRestWrapper( 'http://localhost:8080/gscf/rest', 'getSamples', ['externalStudyID'] )
96     * 
97     * This registers a new method:
98     * 
99         *               public static Object CommunicationManager.getSamples( Object arg )
100     * 
101     * This method has arrity 1 and expects to be given a map. The map is the parameter map
102     * of the rest service getSamples. It maps parameter called "externalStudyID" to some object
103     * that is passed. So, it can be called like as follows:
104     * 
105     *      def sampleList = CommunicationManager.getSamples( [externalStudyID:4711] )
106     * 
107     *  The call will deliver the results of the parameterized rest resource given at:
108     * 
109     *          http://localhost:8080/gscf/rest/nil?externalStudyID=4711
110     *
111     */
112
113    public static addRestWrapper( serverURL, restName, params = [], closure = { return it } ) {
114                if(!serverURL) { throw new Exception("addRestWrapper: REST serverURL is null") }
115                def result
116                try {
117                        CommunicationManager.metaClass.registerStaticMethod( restName ) { Object [] strangeGroovyArgs ->
118                                def map = [:]
119                            def args = strangeGroovyArgs[0]        // groovy nests the parameters of the methods in some other array
120                                if(params.size > 0 )
121                                {
122                                        for( i in 0..(params.size-1) ) {
123                                                def param = params[i]
124                                                map[param] = args[i]
125                                        }
126                                }
127                                result = closure( getRestResource( serverURL, restName, map ) )
128                        } 
129                } catch ( Exception e ) { 
130                        throw new Exception("addRestWrapper: error. Could not retrieve data from RESTFful service. ") 
131                }
132
133                return result
134        }
135
136
137    /**
138     *  This method creates on run time new methods for accessing Grails views that SAM provides for GSCF.
139     *  This method should be called in grails-app/conf/BootStrap.groovy in the GSCF module.
140     */         
141    public static registerRestWrapperMethodsFromSAM() {
142                def url = SAMServerURL
143                addRestWrapper( url+'/rest', 'getQueryResult',  ['query'] )
144    }
145
146
147
148    /**
149     * Give list of missing parameters for a parameter call in a RestController.
150     * 
151     * @params params Map params        The parameter list required by this view.
152     * @params requiredParamers                 List of parameter names that must be provided
153     * @return true, if params has all required parameters, false otherwise
154     */ 
155        static String hasValidParams( params, Object [] requiredParams ) {
156                requiredParams.every { params[it] }
157        }
158
159
160}
Note: See TracBrowser for help on using the repository browser.