Ignore:
Timestamp:
Jan 31, 2011, 8:16:03 PM (6 years ago)
Author:
robert@…
Message:
  • Implemented a cache for module rest calls, to increase performance (see moduleCommunicationService)
  • Implemented searching in module data.
File:
1 edited

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}
Note: See TracChangeset for help on using the changeset viewer.