Changeset 1458

Show
Ignore:
Timestamp:
31-01-11 20:16:03 (3 years ago)
Author:
robert@…
Message:

- Implemented a cache for module rest calls, to increase performance (see moduleCommunicationService)
- Implemented searching in module data.

Location:
trunk
Files:
9 modified

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/dbnp/query/AdvancedQueryController.groovy

    r1456 r1458  
    11package dbnp.query 
     2import dbnp.modules.* 
     3import org.dbnp.gdt.* 
    24 
    35// TODO: Make use of the searchable-plugin possibilities instead of querying the database directly 
     
    911 */ 
    1012class AdvancedQueryController { 
     13        def moduleCommunicationService; 
     14         
    1115        def entitiesToSearchFor = [ 'Study': 'Studies', 'Sample': 'Samples'] 
    1216    def index = { 
     
    5660                def fields = [:]; 
    5761                 
     62                // Retrieve all local search fields 
    5863                getEntities().each { 
    5964                        def entity = getEntity( 'dbnp.studycapturing.' + it ); 
     
    6671                                 
    6772                                fields[ it ] = fieldNames.sort { a, b -> a[0].toUpperCase() + a[1..-1] <=> b[0].toUpperCase() + b[1..-1] }; 
     73                        } 
     74                } 
     75                 
     76                // Loop through all modules and check which fields are searchable 
     77                // Right now, we just combine the results for different entities 
     78                AssayModule.list().each { module -> 
     79                        def callUrl = module.url + '/rest/getQueryableFields' 
     80                        try { 
     81                                def json = moduleCommunicationService.callModuleRestMethodJSON( module.url, callUrl ); 
     82                                def moduleFields = []; 
     83                                entitiesToSearchFor.each { entity ->                                     
     84                                        if( json[ entity.key ] ) { 
     85                                                json[ entity.key ].each { field -> 
     86                                                        moduleFields << field.toString(); 
     87                                                } 
     88                                        } 
     89                                } 
     90                                 
     91                                // Remove 'module' from module name 
     92                                def moduleName = module.name.replace( 'module', '' ).trim() 
     93                                 
     94                                fields[ moduleName ] = moduleFields.unique(); 
     95                        } catch( Exception e ) { 
     96                                log.error( "Error while retrieving queryable fields from " + module.name + ": " + e.getMessage() ) 
    6897                        } 
    6998                } 
  • trunk/grails-app/services/dbnp/modules/ModuleCommunicationService.groovy

    r1455 r1458  
    2020 
    2121class ModuleCommunicationService implements Serializable { 
    22     boolean transactional = false 
     22        boolean transactional = false 
    2323        def authenticationService 
    2424        def moduleNotificationService 
    25          
    26     /** 
    27      * Sends a notification to assay modules that some part of a study has changed. 
    28      *  
    29      * Only modules that have the notify flag set to true will be notified. They will be notified on the URL 
    30      *  
    31      * [moduleUrl]/rest/notifyStudyChange?studyToken=abc 
    32      *  
    33      * Errors that occur when calling this URL are ignored. The module itself is responsible of 
    34      * maintaining a synchronized state. 
    35      *  
    36      * @param study 
    37      * @return 
    38      */ 
     25 
     26        /** 
     27         * Cache containing the contents of different URLs. These urls are 
     28         * saved per user, since the data could be different for different users. 
     29         */ 
     30        def cache = [:] 
     31 
     32        /** 
     33         * Number of seconds to save the data in cache 
     34         */ 
     35        def numberOfSecondsInCache = 10 * 60; 
     36 
     37        /** 
     38         * Sends a notification to assay modules that some part of a study has changed. 
     39         *  
     40         * Only modules that have the notify flag set to true will be notified. They will be notified on the URL 
     41         *  
     42         * [moduleUrl]/rest/notifyStudyChange?studyToken=abc 
     43         *  
     44         * Errors that occur when calling this URL are ignored. The module itself is responsible of 
     45         * maintaining a synchronized state. 
     46         *  
     47         * @param study 
     48         * @return 
     49         */ 
    3950        def invalidateStudy( Study study ) { 
    4051                moduleNotificationService.invalidateStudy( study ); 
    41     } 
    42          
     52        } 
     53 
    4354        /** 
    4455         * Checks whether a specific method on a module is reachable and returns a SC_OK response code.  
     
    5566                try { 
    5667                        return connection.responseCode == HttpServletResponse.SC_OK 
    57                 } catch(e) {  
    58                         return false  
     68                } catch(e) { 
     69                        return false 
    5970                } 
    6071        } 
    61          
     72 
    6273        /** 
    6374         * Calls a rest method on a module 
     
    6879         */ 
    6980        def callModuleRestMethodJSON( consumer, restUrl ) throws Exception { 
    70                 // create a random session token that will be used to allow to module to 
    71                 // sync with gscf prior to presenting the measurement data 
    72                 def sessionToken = UUID.randomUUID().toString() 
    73  
    7481                if (!authenticationService.isLoggedIn()) { 
    7582                        // should not happen because we can only get here when a user is 
     
    7784                        throw new Exception('User is not logged in.') 
    7885                } 
     86 
     87                // Check whether the url is present in cache 
     88                def cacheData = retrieveFromCache( restUrl ); 
     89                if( cacheData && cacheData[ "success" ] ) 
     90                        return cacheData[ "contents" ]; 
     91                else if( cacheData && !cacheData[ "success" ] ) 
     92                        throw new Exception( "Error while fetching data from " + restUrl + " (from cache): " + cacheData[ "error" ] ) 
     93 
     94                // create a random session token that will be used to allow to module to 
     95                // sync with gscf prior to presenting the measurement data 
     96                def sessionToken = UUID.randomUUID().toString() 
    7997 
    8098                // put the session token to work 
     
    90108                        url += '?sessionToken=' + sessionToken 
    91109                } 
    92                  
     110 
    93111                // Perform a call to the url 
    94112                def restResponse 
    95113                try { 
    96114                        def textResponse = url.toURL().getText() 
     115                        println "GSCF call to " + consumer + " URL: " + url 
     116                        println "GSCF response: " + textResponse 
    97117                        restResponse = JSON.parse( textResponse ) 
    98118                } catch (Exception e) { 
     119                        storeErrorInCache( restUrl, e.getMessage() ); 
    99120                        throw new Exception( "An error occurred while fetching " + url + ".", e ) 
    100121                } finally { 
     
    102123                        authenticationService.logOffRemotely(consumer, sessionToken) 
    103124                } 
     125 
     126                // Store the response in cache 
     127                storeInCache( restUrl, restResponse ); 
    104128                 
    105129                return restResponse 
    106130        } 
     131 
     132        /** 
     133         * Checks whether a specific url exists in cache 
     134         * @param url   URL to call 
     135         * @return              true if the url is present in cache 
     136         */ 
     137        def existsInCache( url ) { 
     138                return retrieveFromCache( url ) == null; 
     139        } 
     140 
     141        /** 
     142         * Retrieves the contents of a specific URL from cache 
     143         * @param url   URL to call 
     144         * @return              JSON object with the contents of the URL or null if the url doesn't exist in cache 
     145         */ 
     146        def retrieveFromCache( url ) { 
     147                def user = authenticationService.getLoggedInUser(); 
     148                def userId = user ? user.id : -1; 
     149 
     150                if( cache[ userId ] && cache[ userId ][ url ] && ( System.currentTimeMillis() - cache[ userId ][ url ][ "timestamp" ] ) < numberOfSecondsInCache * 1000 ) { 
     151                        return cache[ userId ][ url ]; 
     152                } else { 
     153                        return null; 
     154                } 
     155        } 
     156 
     157        /** 
     158         * Store the retrieved contents from a url in cache 
     159         * @param url           URL that has been called 
     160         * @param contents      Contents of the URL 
     161         */ 
     162        def storeInCache( url, contents ) { 
     163                def user = authenticationService.getLoggedInUser(); 
     164                def userId = user ? user.id : -1; 
     165 
     166                if( !cache[ userId ] ) 
     167                        cache[ userId ] = [:] 
     168 
     169                cache[ userId ][ url ] = [ 
     170                        "timestamp": System.currentTimeMillis(), 
     171                        "success": true, 
     172                        "contents": contents 
     173                ]; 
     174        } 
     175         
     176        /** 
     177        * Store the retrieved error from a url in cache 
     178        * @param url            URL that has been called 
     179        * @param contents       Contents of the URL 
     180        */ 
     181   def storeErrorInCache( url, error ) { 
     182           def user = authenticationService.getLoggedInUser(); 
     183           def userId = user ? user.id : -1; 
     184 
     185           if( !cache[ userId ] ) 
     186                   cache[ userId ] = [:] 
     187 
     188           cache[ userId ][ url ] = [ 
     189                   "timestamp": System.currentTimeMillis(), 
     190                   "success": false, 
     191                   "error": error 
     192           ]; 
     193   } 
     194 
    107195} 
  • trunk/grails-app/views/advancedQuery/sampleresults.gsp

    r1430 r1458  
    2727</p> 
    2828 
     29 
    2930<g:if test="${search.getNumResults() > 0}"> 
    3031 
     
    3233                <thead> 
    3334                <tr> 
    34                         <th colspan="2"></th> 
    3535                        <th>Study</th> 
    3636                        <th>Name</th> 
  • trunk/grails-app/views/advancedQuery/studyresults.gsp

    r1430 r1458  
    2626        resulted in ${search.getNumResults()} <g:if test="${search.getNumResults() == 1}">study</g:if><g:else>studies</g:else>. 
    2727</p> 
    28  
    2928<g:if test="${search.getNumResults() > 0}"> 
    3029 
  • trunk/grails-app/views/user/search.gsp

    r1430 r1458  
    6565        <g:if test='${searched}'> 
    6666 
    67 <% 
    68 def queryParams = [username: username, enabled: enabled, accountExpired: accountExpired, accountLocked: accountLocked, passwordExpired: passwordExpired] 
    69 %> 
     67        <% 
     68        def queryParams = [username: username, enabled: enabled, accountExpired: accountExpired, accountLocked: accountLocked, passwordExpired: passwordExpired] 
     69        %> 
    7070 
    7171        <div class="list"> 
  • trunk/src/groovy/dbnp/query/Criterion.groovy

    r1457 r1458  
    2525 
    2626        /** 
    27          * Checks if the given object (with template) that satisfies the given criterion. 
    28          * 
    29          * @param entity                Entity to check for criterion satisfaction. Should be a child of template entity 
     27         * Retrieves the correct value for this criterion in the given object (with template) 
     28         * 
     29         * @param entity                Entity to check for value. Should be a child of template entity 
    3030         * @param criterion     Criterion to match on 
    31          * @return                      True iff there the entity satisfies the given criterion. 
    32          */ 
    33         public boolean matchOne( TemplateEntity entity ) { 
     31         * @return                      Value of the given field or null if the field doesn't exist 
     32         */ 
     33        public def getFieldValue( TemplateEntity entity ) { 
     34                if( entity == null ) 
     35                        return null; 
     36 
    3437                try { 
    3538                        def fieldValue 
     
    4043                        } 
    4144 
    42                         return this.match( fieldValue ); 
     45                        return fieldValue 
    4346                } catch( Exception e ) { 
    4447                        // An exception occurs if the given field doesn't exist. In that case, this criterion will fail. 
    4548                        // TODO: Maybe give the user a choice whether he want's to include these studies or not 
    46                         return false; 
    47                 } 
     49                        return null; 
     50                } 
     51        } 
     52 
     53        /** 
     54         * Checks if the given object (with template) that satisfies the given criterion. 
     55         * 
     56         * @param entity                Entity to check for criterion satisfaction. Should be a child of template entity 
     57         * @param criterion     Criterion to match on 
     58         * @return                      True iff there the entity satisfies the given criterion. 
     59         */ 
     60        public boolean matchEntity( TemplateEntity entity ) { 
     61                def fieldValue = this.getFieldValue( entity ); 
     62 
     63                // Null is returned, the given field doesn't exist. In that case, this criterion will fail. 
     64                // TODO: Maybe give the user a choice whether he want's to include these studies or not 
     65                if( fieldValue == null ) 
     66                        return false; 
     67 
     68                return this.match( fieldValue ); 
    4869        } 
    4970 
     
    5576         * @return                              True iff there is any entity in the list that satisfies the given criterion. 
    5677         */ 
    57         public boolean matchAny( List entityList ) { 
     78        public boolean matchAnyEntity( List<TemplateEntity> entityList ) { 
    5879                for( entity in entityList ) { 
    59                         if( matchOne( entity ) ) 
     80                        if( matchOneEntity( entity ) ) 
    6081                                return true; 
    6182                } 
     
    7091         * @return                              True iff all entities satisfy the given criterion. 
    7192         */ 
     93        public boolean matchAllEntities( List<TemplateEntity> entityList ) { 
     94                for( entity in entityList ) { 
     95                        if( !matchOneEntity( entity ) ) 
     96                                return false; 
     97                } 
     98                return true; 
     99        } 
     100 
     101        /** 
     102         * Checks for all values in the given List, if there is any value that satisfies the given criterion. 
     103         * 
     104         * @param entityList            List with values. 
     105         * @param criterion             Criterion to match on 
     106         * @return                              True iff there is any value in the list that satisfies the given criterion. 
     107         */ 
     108        public boolean matchAny( List valueList ) { 
     109                for( value in valueList ) { 
     110                        if( match( value ) ) 
     111                                return true; 
     112                } 
     113                return false; 
     114        } 
     115 
     116        /** 
     117         * Checks for all values in the given List, if all values satisfy the given criterion. 
     118         * 
     119         * @param entityList            List with values. 
     120         * @param criterion             Criterion to match on 
     121         * @return                              True iff all values satisfy the given criterion. 
     122         */ 
    72123        public boolean matchAll( List entityList ) { 
    73                 for( entity in entityList ) { 
    74                         if( !matchOne( entity ) ) 
     124                for( value in valueList ) { 
     125                        if( !match( value ) ) 
    75126                                return false; 
    76127                } 
     
    87138                if( fieldValue == null ) 
    88139                        return false; 
    89                          
     140 
    90141                def classname = fieldValue.class.getName(); 
    91142                classname = classname[classname.lastIndexOf( '.' ) + 1..-1].toLowerCase(); 
    92                  
     143 
    93144                println "Match " + fieldValue + " of class " + classname + " with " + this 
    94                  
     145 
    95146                try { 
    96147                        switch( classname ) { 
     
    152203                        Date dateCriterion = new SimpleDateFormat( "yyyy-MM-dd" ).parse( value ); 
    153204                        Date fieldDate = new Date( fieldValue.getTime() ); 
    154                          
     205 
    155206                        // Clear time in order to just compare dates 
    156207                        dateCriterion.clearTime(); 
    157208                        fieldDate.clearTime(); 
    158                          
     209 
    159210                        return compareValues( fieldDate, this.operator, dateCriterion ) 
    160211                } catch( Exception e ) { 
     
    232283 
    233284                        // Numbers are taken to be seconds, if a non-numeric value is given, try to parse it 
    234                         if( value.toString().isNumber() ) { 
     285                        if( value.toString().isLong() ) { 
    235286                                rt = new RelTime( Long.parseLong( value.toString() ) ); 
    236287                        } else { 
    237288                                rt = new RelTime( value.toString() ); 
    238289                        } 
    239                          
     290 
    240291                        return compareValues( fieldValue, this.operator, rt ); 
    241292                } catch( Exception e ) { 
  • trunk/src/groovy/dbnp/query/SampleSearch.groovy

    r1456 r1458  
    1616 
    1717import dbnp.studycapturing.* 
     18import org.dbnp.gdt.* 
    1819 
    1920class SampleSearch extends Search { 
     21         
    2022        public SampleSearch() { 
    2123                this.entity = "Sample"; 
     
    9395                samples = filterOnAssayCriteria( samples ); 
    9496                 
     97                samples = filterOnModuleCriteria( samples ); 
     98                 
    9599                // Save matches 
    96100                results = samples; 
     
    103107         */ 
    104108        protected List filterOnStudyCriteria( List studies ) { 
    105                 return filterEntityList( studies, getEntityCriteria( 'Study' ), { study, criterion -> 
    106                         return criterion.matchOne( study ); 
    107                 }); 
     109                return filterOnTemplateEntityCriteria(studies, "Study", { study, criterion -> return criterion.getFieldValue( study ) }) 
    108110        } 
    109111 
     
    114116         */ 
    115117        protected List filterOnSubjectCriteria( List samples ) { 
    116                 return filterEntityList( samples, getEntityCriteria( 'Subject' ), { sample, criterion -> 
    117                         if( !sample.parentSubject ) 
    118                                 return false 
    119  
    120                         return criterion.matchOne( sample.parentSubject ); 
    121                 }); 
     118                return filterOnTemplateEntityCriteria(samples, "Subject", { sample, criterion -> 
     119                        return criterion.getFieldValue( sample.parentSubject ); 
     120                }) 
    122121        } 
    123122 
     
    128127         */ 
    129128        protected List filterOnSampleCriteria( List samples ) { 
    130                 return filterEntityList( samples, getEntityCriteria( 'Sample' ), { sample, criterion -> 
    131                         if( !sample  ) 
    132                                 return false 
    133  
    134                         return criterion.matchOne( sample ); 
    135                 }); 
     129                return filterOnTemplateEntityCriteria(samples, "Sample", { sample, criterion -> 
     130                        return criterion.getFieldValue( sample ); 
     131                }) 
    136132        } 
    137133 
     
    142138         */ 
    143139        protected List filterOnEventCriteria( List samples ) { 
    144                 println "Event criteria: " + getEntityCriteria( 'Event' ) 
    145                 return filterEntityList( samples, getEntityCriteria( 'Event' ), { sample, criterion -> 
     140                return filterOnTemplateEntityCriteria(samples, "Event", { sample, criterion -> 
    146141                        if( !sample || !sample.parentEventGroup || !sample.parentEventGroup.events || sample.parentEventGroup.events.size() == 0 ) 
    147                                 return false 
    148                  
    149                         return criterion.matchAny( sample.parentEventGroup.events.toList() ); 
    150                 }); 
     142                                return null 
     143 
     144                        return criterion.getFieldValue( sample.parentEventGroup.events.toList() ); 
     145                }) 
    151146        } 
    152147 
     
    157152         */ 
    158153        protected List filterOnSamplingEventCriteria( List samples ) { 
    159                 return filterEntityList( samples, getEntityCriteria( 'SamplingEvent' ), { sample, criterion -> 
    160                         if( !sample.parentEvent ) 
    161                                 return false 
    162  
    163                         return criterion.matchOne( sample.parentEvent ); 
    164                 }); 
    165         } 
    166  
     154                return filterOnTemplateEntityCriteria(samples, "SamplingEvent", { sample, criterion -> 
     155                        return criterion.getFieldValue( sample.parentEvent ); 
     156                }) 
     157        } 
    167158 
    168159        /** 
     
    180171                // There is no sample.assays property, so we have to look for assays another way: just find 
    181172                // all assays that match the criteria 
    182                 def assays = filterEntityList( Assay.list(), getEntityCriteria( 'Assay' ), { assay, criterion -> 
     173                def criteria = getEntityCriteria( 'Assay' ); 
     174                def assays = filterEntityList( Assay.list(), criteria, { assay, criterion -> 
    183175                        if( !assay ) 
    184176                                return false 
     
    190182                if( assays.size() == 0 ) 
    191183                        return []; 
     184                 
     185                // Save sample data for later use 
     186                saveResultFields( samples, criteria, { sample, criterion ->  
     187                         def sampleAssays = Assay.findByStudy( sample.parent ).findAll { it.samples?.contains( sample ) }; 
     188                         if( sampleAssays && sampleAssays.size() > 0 )  
     189                                return sampleAssays.collect( criterion.getFieldValue( it ) ) 
     190                        else  
     191                                return null 
     192                }); 
    192193                         
    193194                // Now filter the samples on whether they are attached to the filtered assays 
     
    208209                } 
    209210        } 
    210  
    211211} 
  • trunk/src/groovy/dbnp/query/Search.groovy

    r1457 r1458  
    1616package dbnp.query 
    1717 
     18import groovy.lang.Closure; 
     19 
    1820import java.text.SimpleDateFormat 
     21import java.util.List; 
     22 
     23import org.springframework.context.ApplicationContext 
     24import org.codehaus.groovy.grails.commons.ApplicationHolder; 
     25 
    1926import org.dbnp.gdt.* 
    2027 
     
    2431        protected List criteria; 
    2532        protected List results; 
     33        protected Map resultFields = [:]; 
    2634 
    2735        public List getCriteria() { return criteria; } 
     
    3038        public List getResults() { return results; } 
    3139        public void setResults( List r ) { results = r; } 
     40         
     41        public Map getResultFields() { return resultFields; } 
     42        public void setResultFields( Map r ) { resultFields = r; } 
    3243 
    3344        /** 
     
    156167 
    157168        } 
     169         
     170         
     171        /** 
     172         * Filters the given list of studies on the study criteria 
     173         * @param studies               Original list of studies 
     174         * @param entity                Name of the entity to check the criteria for 
     175         * @param valueCallback Callback having a study and criterion as input, returning the value of the field to check on 
     176         * @return                              List with all studies that match the Criteria 
     177         */ 
     178        protected List filterOnTemplateEntityCriteria( List studies, String entityName, Closure valueCallback ) { 
     179                def criteria = getEntityCriteria( entityName ); 
     180                def checkCallback = { study, criterion -> 
     181                        def value = valueCallback( study, criterion ); 
     182                         
     183                        if( value == null ) 
     184                                return false 
     185                        if( value instanceof Collection ) { 
     186                                return criterion.matchAny( value ) 
     187                        } else { 
     188                                return criterion.match( value ); 
     189                        } 
     190                } 
     191 
     192                // Save the value of this entity for later use 
     193                saveResultFields( studies, criteria, valueCallback ); 
     194 
     195                return filterEntityList( studies, criteria, checkCallback); 
     196        } 
     197 
     198        /** 
     199        * Filters the given list of entities on the module criteria 
     200        * @param entities       Original list of entities. Entities should expose a giveUUID() method to give the token. 
     201        * @return                       List with all entities that match the module criteria 
     202        */ 
     203        protected List filterOnModuleCriteria( List entities ) { 
     204                // An empty list can't be filtered more than is has been now 
     205                if( !entities || entities.size() == 0 ) 
     206                        return []; 
     207                         
     208                // Determine the moduleCommunicationService 
     209                ApplicationContext ctx = (ApplicationContext)ApplicationHolder.getApplication().getMainContext(); 
     210                def moduleCommunicationService = ctx.getBean("moduleCommunicationService"); 
     211                         
     212                // Loop through all modules and check whether criteria have been given 
     213                // for that module 
     214                AssayModule.list().each { module -> 
     215                        // Remove 'module' from module name 
     216                        def moduleName = module.name.replace( 'module', '' ).trim() 
     217                        def moduleCriteria = getEntityCriteria( moduleName ); 
     218                         
     219                        if( moduleCriteria && moduleCriteria.size() > 0 ) { 
     220                                println "Filter " + entities.size() + " entities on " + module.name + " criteria: " + moduleCriteria.size(); 
     221 
     222                                // Retrieve the data from the module 
     223                                def tokens = entities.collect { it.giveUUID() }.unique(); 
     224                                def fields = moduleCriteria.collect { it.field }.unique(); 
     225                                 
     226                                def callUrl = module.url + '/rest/getQueryableFieldData?entity=' + this.entity 
     227                                tokens.sort().each { callUrl += "&tokens=" + it.encodeAsURL() } 
     228                                fields.sort().each { callUrl += "&fields=" + it.encodeAsURL() } 
     229                                 
     230                                try { 
     231                                        def json = moduleCommunicationService.callModuleRestMethodJSON( module.url, callUrl ); 
     232 
     233                                        // The data has been retrieved. Now walk through all criteria to filter the samples 
     234                                        entities = filterEntityList( entities, moduleCriteria, { entity, criterion -> 
     235                                                // Find the value of the field in this sample. That value is still in the 
     236                                                // JSON object 
     237                                                def token = entity.giveUUID() 
     238                                                if( !json[ token ] || json[ token ][ criterion.field ] == null ) 
     239                                                        return false; 
     240 
     241                                                // Check whether a list or string is given 
     242                                                def value = json[ token ][ criterion.field ]; 
     243                                                 
     244                                                // Save the value of this entity for later use 
     245                                                saveResultField( entity.id, criterion.field, value ) 
     246 
     247                                                if( !( value instanceof Collection ) ) { 
     248                                                        value = [ value ]; 
     249                                                } 
     250                                                 
     251                                                // Loop through all values and match any 
     252                                                for( val in value ) { 
     253                                                        // Convert numbers to a long or double in order to process them correctly 
     254                                                        val = val.toString(); 
     255                                                        if( val.isLong() ) { 
     256                                                                val = Long.parseLong( val ); 
     257                                                        } else if( val.isDouble() ) { 
     258                                                                val = Double.parseDouble( val ); 
     259                                                        } 
     260                                                         
     261                                                        if( criterion.match( val ) ) 
     262                                                                return true; 
     263                                                } 
     264                                                 
     265                                                return false; 
     266                                        }); 
     267                                                                                 
     268                                } catch( Exception e ) { 
     269                                        println( "Error while retrieving data from " + module.name + ": " + e.getMessage() ) 
     270                                } 
     271                        } 
     272                } 
     273                 
     274                return entities; 
     275        } 
     276         
     277        /** 
     278         * Saves data about template entities to use later on. This data is copied to a special 
     279         * structure to make it compatible with data fetched from other modules. Ses also saveResultField() method 
     280         * @param entities                      List of template entities to find data in 
     281         * @param criteria                      Criteria to search for 
     282         * @param valueCallback         Callback to retrieve a specific field from the entity 
     283         */ 
     284        protected void saveResultFields( entities, criteria, valueCallback ) { 
     285                for( criterion in criteria ) { 
     286                        for( entity in entities ) { 
     287                                saveResultField( entity.id, criterion.field, valueCallback( entity, criterion ) ) 
     288                        } 
     289                } 
     290        } 
     291 
     292         
     293        /** 
     294         * Saves a specific field of an object to use later on. Especially useful when looking up data from other modules. 
     295         * @param id            ID of the object 
     296         * @param fieldName     Field name that has been searched 
     297         * @param value         Value of the field 
     298         */ 
     299        protected void saveResultField( id, fieldName, value ) { 
     300                if( resultFields[ id ] == null ) 
     301                        resultFields[ id ] = [:] 
     302                 
     303                resultFields[ id ][ fieldName ] = value; 
     304        } 
    158305} 
  • trunk/src/groovy/dbnp/query/StudySearch.groovy

    r1456 r1458  
    1515package dbnp.query 
    1616 
     17import java.util.List; 
     18 
    1719import dbnp.studycapturing.* 
     20import org.dbnp.gdt.* 
    1821 
    1922class StudySearch extends Search { 
     
    7376                studies = filterOnAssayCriteria( studies ); 
    7477 
     78                studies = filterOnModuleCriteria( studies ); 
     79                 
    7580                // Save matches 
    7681                results = studies; 
    7782        } 
    78  
     83         
    7984        /** 
    8085         * Filters the given list of studies on the study criteria 
    8186         * @param studies       Original list of studies 
    82          * @return                      List with all studies that match the Study-criteria 
     87         * @return                      List with all studies that match the Study criteria 
    8388         */ 
    8489        protected List filterOnStudyCriteria( List studies ) { 
    85                 return filterEntityList( studies, getEntityCriteria( 'Study' ), { study, criterion -> 
    86                         return criterion.matchOne( study ); 
    87                 }); 
     90                return filterOnTemplateEntityCriteria(studies, "Study", { study, criterion -> return criterion.getFieldValue( study ) }) 
    8891        } 
    8992 
     
    9497         */ 
    9598        protected List filterOnSubjectCriteria( List studies ) { 
    96                 return filterEntityList( studies, getEntityCriteria( 'Subject' ), { study, criterion -> 
    97                         if( !study.subjects?.size() ) 
    98                                 return false 
    99  
    100                         return criterion.matchAny( study.subjects ); 
    101                 }); 
     99                return filterOnTemplateEntityCriteria(studies, "Subject", { study, criterion ->  
     100                        return study.subjects?.collect { criterion.getFieldValue( it ); } 
     101                }) 
    102102        } 
    103103 
     
    108108         */ 
    109109        protected List filterOnSampleCriteria( List studies ) { 
    110                 return filterEntityList( studies, getEntityCriteria( 'Sample' ), { study, criterion -> 
    111                         if( !study.samples?.size() ) 
    112                                 return false 
    113  
    114                         return criterion.matchAny( study.samples ); 
    115                 }); 
     110                return filterOnTemplateEntityCriteria(studies, "Sample", { study, criterion -> 
     111                        return study.samples?.collect { criterion.getFieldValue( it ); } 
     112                }) 
    116113        } 
    117114 
     
    122119         */ 
    123120        protected List filterOnEventCriteria( List studies ) { 
    124                 return filterEntityList( studies, getEntityCriteria( 'Event' ), { study, criterion -> 
    125                         if( !study.events?.size() ) 
    126                                 return false 
    127  
    128                         return criterion.matchAny( study.events ); 
    129                 }); 
     121                return filterOnTemplateEntityCriteria(studies, "Event", { study, criterion ->  
     122                        return study.events?.collect { criterion.getFieldValue( it ); } 
     123                }) 
    130124        } 
    131125         
     
    136130        */ 
    137131   protected List filterOnSamplingEventCriteria( List studies ) { 
    138            return filterEntityList( studies, getEntityCriteria( 'SamplingEvent' ), { study, criterion -> 
    139                    if( !study.samplingEvents?.size() ) 
    140                            return false 
    141  
    142                         return criterion.matchAny( study.samplingEvents ); 
    143            }); 
     132                return filterOnTemplateEntityCriteria(studies, "SamplingEvent", { study, criterion ->  
     133                        return study.samplingEvents?.collect { criterion.getFieldValue( it ); } 
     134                }) 
    144135   } 
    145  
    146136         
    147137        /** 
     
    151141         */ 
    152142        protected List filterOnAssayCriteria( List studies ) { 
    153                 return filterEntityList( studies, getEntityCriteria( 'Assay' ), { study, criterion -> 
    154                         if( !study.assays?.size() ) 
    155                                 return false 
    156  
    157                         return criterion.matchAny( study.assays ); 
    158                 }); 
     143                return filterOnTemplateEntityCriteria(studies, "Assay", { study, criterion -> 
     144                        return study.assays?.collect { criterion.getFieldValue( it ); } 
     145                }) 
    159146        } 
    160147}