Changeset 1458
- Timestamp:
- Jan 31, 2011, 8:16:03 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/dbnp/query/AdvancedQueryController.groovy
r1456 r1458 1 1 package dbnp.query 2 import dbnp.modules.* 3 import org.dbnp.gdt.* 2 4 3 5 // TODO: Make use of the searchable-plugin possibilities instead of querying the database directly … … 9 11 */ 10 12 class AdvancedQueryController { 13 def moduleCommunicationService; 14 11 15 def entitiesToSearchFor = [ 'Study': 'Studies', 'Sample': 'Samples'] 12 16 def index = { … … 56 60 def fields = [:]; 57 61 62 // Retrieve all local search fields 58 63 getEntities().each { 59 64 def entity = getEntity( 'dbnp.studycapturing.' + it ); … … 66 71 67 72 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() ) 68 97 } 69 98 } -
trunk/grails-app/services/dbnp/modules/ModuleCommunicationService.groovy
r1455 r1458 20 20 21 21 class ModuleCommunicationService implements Serializable { 22 22 boolean transactional = false 23 23 def authenticationService 24 24 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 */ 39 50 def invalidateStudy( Study study ) { 40 51 moduleNotificationService.invalidateStudy( study ); 41 42 52 } 53 43 54 /** 44 55 * Checks whether a specific method on a module is reachable and returns a SC_OK response code. … … 55 66 try { 56 67 return connection.responseCode == HttpServletResponse.SC_OK 57 } catch(e) { 58 return false 68 } catch(e) { 69 return false 59 70 } 60 71 } 61 72 62 73 /** 63 74 * Calls a rest method on a module … … 68 79 */ 69 80 def callModuleRestMethodJSON( consumer, restUrl ) throws Exception { 70 // create a random session token that will be used to allow to module to71 // sync with gscf prior to presenting the measurement data72 def sessionToken = UUID.randomUUID().toString()73 74 81 if (!authenticationService.isLoggedIn()) { 75 82 // should not happen because we can only get here when a user is … … 77 84 throw new Exception('User is not logged in.') 78 85 } 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() 79 97 80 98 // put the session token to work … … 90 108 url += '?sessionToken=' + sessionToken 91 109 } 92 110 93 111 // Perform a call to the url 94 112 def restResponse 95 113 try { 96 114 def textResponse = url.toURL().getText() 115 println "GSCF call to " + consumer + " URL: " + url 116 println "GSCF response: " + textResponse 97 117 restResponse = JSON.parse( textResponse ) 98 118 } catch (Exception e) { 119 storeErrorInCache( restUrl, e.getMessage() ); 99 120 throw new Exception( "An error occurred while fetching " + url + ".", e ) 100 121 } finally { … … 102 123 authenticationService.logOffRemotely(consumer, sessionToken) 103 124 } 125 126 // Store the response in cache 127 storeInCache( restUrl, restResponse ); 104 128 105 129 return restResponse 106 130 } 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 107 195 } -
trunk/grails-app/views/advancedQuery/sampleresults.gsp
r1430 r1458 27 27 </p> 28 28 29 29 30 <g:if test="${search.getNumResults() > 0}"> 30 31 … … 32 33 <thead> 33 34 <tr> 34 <th colspan="2"></th>35 35 <th>Study</th> 36 36 <th>Name</th> -
trunk/grails-app/views/advancedQuery/studyresults.gsp
r1430 r1458 26 26 resulted in ${search.getNumResults()} <g:if test="${search.getNumResults() == 1}">study</g:if><g:else>studies</g:else>. 27 27 </p> 28 29 28 <g:if test="${search.getNumResults() > 0}"> 30 29 -
trunk/grails-app/views/user/search.gsp
r1430 r1458 65 65 <g:if test='${searched}'> 66 66 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 %> 70 70 71 71 <div class="list"> -
trunk/src/groovy/dbnp/query/Criterion.groovy
r1457 r1458 25 25 26 26 /** 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 entity27 * 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 30 30 * @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 34 37 try { 35 38 def fieldValue … … 40 43 } 41 44 42 return this.match( fieldValue );45 return fieldValue 43 46 } catch( Exception e ) { 44 47 // An exception occurs if the given field doesn't exist. In that case, this criterion will fail. 45 48 // 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 ); 48 69 } 49 70 … … 55 76 * @return True iff there is any entity in the list that satisfies the given criterion. 56 77 */ 57 public boolean matchAny ( ListentityList ) {78 public boolean matchAnyEntity( List<TemplateEntity> entityList ) { 58 79 for( entity in entityList ) { 59 if( matchOne ( entity ) )80 if( matchOneEntity( entity ) ) 60 81 return true; 61 82 } … … 70 91 * @return True iff all entities satisfy the given criterion. 71 92 */ 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 */ 72 123 public boolean matchAll( List entityList ) { 73 for( entity in entityList ) {74 if( !match One( entity) )124 for( value in valueList ) { 125 if( !match( value ) ) 75 126 return false; 76 127 } … … 87 138 if( fieldValue == null ) 88 139 return false; 89 140 90 141 def classname = fieldValue.class.getName(); 91 142 classname = classname[classname.lastIndexOf( '.' ) + 1..-1].toLowerCase(); 92 143 93 144 println "Match " + fieldValue + " of class " + classname + " with " + this 94 145 95 146 try { 96 147 switch( classname ) { … … 152 203 Date dateCriterion = new SimpleDateFormat( "yyyy-MM-dd" ).parse( value ); 153 204 Date fieldDate = new Date( fieldValue.getTime() ); 154 205 155 206 // Clear time in order to just compare dates 156 207 dateCriterion.clearTime(); 157 208 fieldDate.clearTime(); 158 209 159 210 return compareValues( fieldDate, this.operator, dateCriterion ) 160 211 } catch( Exception e ) { … … 232 283 233 284 // Numbers are taken to be seconds, if a non-numeric value is given, try to parse it 234 if( value.toString().is Number() ) {285 if( value.toString().isLong() ) { 235 286 rt = new RelTime( Long.parseLong( value.toString() ) ); 236 287 } else { 237 288 rt = new RelTime( value.toString() ); 238 289 } 239 290 240 291 return compareValues( fieldValue, this.operator, rt ); 241 292 } catch( Exception e ) { -
trunk/src/groovy/dbnp/query/SampleSearch.groovy
r1456 r1458 16 16 17 17 import dbnp.studycapturing.* 18 import org.dbnp.gdt.* 18 19 19 20 class SampleSearch extends Search { 21 20 22 public SampleSearch() { 21 23 this.entity = "Sample"; … … 93 95 samples = filterOnAssayCriteria( samples ); 94 96 97 samples = filterOnModuleCriteria( samples ); 98 95 99 // Save matches 96 100 results = samples; … … 103 107 */ 104 108 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 ) }) 108 110 } 109 111 … … 114 116 */ 115 117 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 }) 122 121 } 123 122 … … 128 127 */ 129 128 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 }) 136 132 } 137 133 … … 142 138 */ 143 139 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 -> 146 141 if( !sample || !sample.parentEventGroup || !sample.parentEventGroup.events || sample.parentEventGroup.events.size() == 0 ) 147 return false148 149 return criterion. matchAny( sample.parentEventGroup.events.toList() );150 }) ;142 return null 143 144 return criterion.getFieldValue( sample.parentEventGroup.events.toList() ); 145 }) 151 146 } 152 147 … … 157 152 */ 158 153 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 } 167 158 168 159 /** … … 180 171 // There is no sample.assays property, so we have to look for assays another way: just find 181 172 // 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 -> 183 175 if( !assay ) 184 176 return false … … 190 182 if( assays.size() == 0 ) 191 183 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 }); 192 193 193 194 // Now filter the samples on whether they are attached to the filtered assays … … 208 209 } 209 210 } 210 211 211 } -
trunk/src/groovy/dbnp/query/Search.groovy
r1457 r1458 16 16 package dbnp.query 17 17 18 import groovy.lang.Closure; 19 18 20 import java.text.SimpleDateFormat 21 import java.util.List; 22 23 import org.springframework.context.ApplicationContext 24 import org.codehaus.groovy.grails.commons.ApplicationHolder; 25 19 26 import org.dbnp.gdt.* 20 27 … … 24 31 protected List criteria; 25 32 protected List results; 33 protected Map resultFields = [:]; 26 34 27 35 public List getCriteria() { return criteria; } … … 30 38 public List getResults() { return results; } 31 39 public void setResults( List r ) { results = r; } 40 41 public Map getResultFields() { return resultFields; } 42 public void setResultFields( Map r ) { resultFields = r; } 32 43 33 44 /** … … 156 167 157 168 } 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 } 158 305 } -
trunk/src/groovy/dbnp/query/StudySearch.groovy
r1456 r1458 15 15 package dbnp.query 16 16 17 import java.util.List; 18 17 19 import dbnp.studycapturing.* 20 import org.dbnp.gdt.* 18 21 19 22 class StudySearch extends Search { … … 73 76 studies = filterOnAssayCriteria( studies ); 74 77 78 studies = filterOnModuleCriteria( studies ); 79 75 80 // Save matches 76 81 results = studies; 77 82 } 78 83 79 84 /** 80 85 * Filters the given list of studies on the study criteria 81 86 * @param studies Original list of studies 82 * @return List with all studies that match the Study -criteria87 * @return List with all studies that match the Study criteria 83 88 */ 84 89 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 ) }) 88 91 } 89 92 … … 94 97 */ 95 98 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 }) 102 102 } 103 103 … … 108 108 */ 109 109 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 }) 116 113 } 117 114 … … 122 119 */ 123 120 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 }) 130 124 } 131 125 … … 136 130 */ 137 131 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 }) 144 135 } 145 146 136 147 137 /** … … 151 141 */ 152 142 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 }) 159 146 } 160 147 }
Note: See TracChangeset
for help on using the changeset viewer.