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.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • 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}