- Timestamp:
- Feb 2, 2011, 4:40:22 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/dbnp/query/AdvancedQueryController.groovy
r1458 r1482 12 12 class AdvancedQueryController { 13 13 def moduleCommunicationService; 14 def authenticationService 15 16 def entitiesToSearchFor = [ 'Study': 'Studies', 'Sample': 'Samples'] 14 17 15 def entitiesToSearchFor = [ 'Study': 'Studies', 'Sample': 'Samples'] 16 def index = { 17 [entitiesToSearchFor: entitiesToSearchFor, searchableFields: getSearchableFields()] 18 } 18 /** 19 * Shows search screen 20 */ 21 def index = { 22 // Check whether criteria have been given before 23 def criteria = []; 24 if( params.criteria ) { 25 criteria = parseCriteria( params.criteria, false ) 26 } 27 [entitiesToSearchFor: entitiesToSearchFor, searchableFields: getSearchableFields(), criteria: criteria] 28 } 19 29 20 30 /** … … 38 48 // Create a search object and let it do the searching 39 49 Search search; 40 String view ;50 String view = determineView( params.entity ); 41 51 switch( params.entity ) { 42 case "Study": search = new StudySearch(); view = "studyresults";break;43 case "Sample": search = new SampleSearch(); view = "sampleresults";break;44 45 // This exception will only be thrown if the entitiesToSearchFor contains more entities than 52 case "Study": search = new StudySearch(); break; 53 case "Sample": search = new SampleSearch(); break; 54 55 // This exception will only be thrown if the entitiesToSearchFor contains more entities than 46 56 // mentioned in this switch structure. 47 default: throw new Exception( "Can't search for entities of type " + params.entity ); 48 } 49 57 default: throw new Exception( "Can't search for entities of type " + params.entity ); 58 } 50 59 search.execute( parseCriteria( params.criteria ) ); 51 52 render( view: view, model: [search: search] ); 60 61 // Save search in session 62 def queryId = saveSearch( search ); 63 render( view: view, model: [search: search, queryId: queryId] ); 64 } 65 66 /** 67 * Removes a specified search from session 68 * @param id queryId of the search to discard 69 */ 70 def discard = { 71 Integer queryId 72 try { 73 queryId = params.id as Integer 74 } catch( Exception e ) { 75 flash.error = "Incorrect search ID given to discard" 76 redirect( action: "index" ); 77 return 78 } 79 80 discardSearch( queryId ); 81 flash.message = "Search has been discarded" 82 redirect( action: "list" ); 83 } 84 85 /** 86 * Shows a specified search from session 87 * @param id queryId of the search to show 88 */ 89 def show = { 90 Integer queryId 91 try { 92 queryId = params.id as Integer 93 } catch( Exception e ) { 94 flash.error = "Incorrect search ID given to show" 95 redirect( action: "index" ); 96 return 97 } 98 99 // Retrieve the search from session 100 Search s = retrieveSearch( queryId ); 101 if( !s ) { 102 flash.message = "Specified search could not be found" 103 redirect( action: "index" ); 104 return; 105 } 106 107 // Determine which view to show 108 def view = determineView( s.entity ); 109 render( view: view, model: [search: s, queryId: queryId] ); 110 } 111 112 /** 113 * Shows a list of searches that have been saved in session 114 * @param id queryId of the search to show 115 */ 116 def list = { 117 def searches = listSearches(); 118 119 if( !searches || searches.size() == 0 ) { 120 flash.message = "No previous searches found"; 121 redirect( action: "index" ); 122 return; 123 } 124 [searches: searches] 53 125 } 54 126 127 /** 128 * Shows a search screen where the user can search within the results of another search 129 * @param id queryId of the search to search in 130 */ 131 def searchIn = { 132 Integer queryId 133 try { 134 queryId = params.id as Integer 135 } catch( Exception e ) { 136 flash.error = "Incorrect search ID given to show" 137 redirect( action: "index" ); 138 return 139 } 140 141 // Retrieve the search from session 142 Search s = retrieveSearch( queryId ); 143 if( !s ) { 144 flash.message = "Specified search could not be found" 145 redirect( action: "index" ); 146 return; 147 } 148 149 redirect( action: "index", params: [ "criteria.0.entityfield": s.entity, "criteria.0.operator": "in", "criteria.0.value": queryId ]) 150 } 151 152 protected String determineView( String entity ) { 153 switch( entity ) { 154 case "Study": return "studyresults"; break; 155 case "Sample": return "sampleresults"; break; 156 default: return "results"; break; 157 } 158 } 159 55 160 /** 56 161 * Returns a map of entities with the names of the fields the user can search on … … 59 164 protected def getSearchableFields() { 60 165 def fields = [:]; 61 166 62 167 // Retrieve all local search fields 63 168 getEntities().each { 64 169 def entity = getEntity( 'dbnp.studycapturing.' + it ); 65 170 66 171 if( entity ) { 67 172 def domainFields = entity.giveDomainFields(); 68 173 def templateFields = TemplateField.findAllByEntity( entity ) 69 174 70 175 def fieldNames = ( domainFields + templateFields ).collect { it.name }.unique() + 'Template' 71 176 72 177 fields[ it ] = fieldNames.sort { a, b -> a[0].toUpperCase() + a[1..-1] <=> b[0].toUpperCase() + b[1..-1] }; 73 178 } 74 179 } 75 180 76 181 // Loop through all modules and check which fields are searchable 77 182 // Right now, we just combine the results for different entities … … 81 186 def json = moduleCommunicationService.callModuleRestMethodJSON( module.url, callUrl ); 82 187 def moduleFields = []; 83 entitiesToSearchFor.each { entity -> 188 entitiesToSearchFor.each { entity -> 84 189 if( json[ entity.key ] ) { 85 190 json[ entity.key ].each { field -> … … 88 193 } 89 194 } 90 195 91 196 // Remove 'module' from module name 92 197 def moduleName = module.name.replace( 'module', '' ).trim() 93 198 94 199 fields[ moduleName ] = moduleFields.unique(); 95 200 } catch( Exception e ) { … … 97 202 } 98 203 } 99 204 100 205 return fields; 101 206 } 102 207 103 208 /** 104 209 * Parses the criteria from the query form given by the user … … 115 220 * 1.field: d 116 221 * ] 117 * 118 * @return List with Criterion objects119 */ 120 protected List parseCriteria( def c) {222 * @param parseSearchIds Determines whether searches are returned instead of their ids 223 * @return List with Criterion objects 224 */ 225 protected List parseCriteria( def formCriteria, def parseSearchIds = true ) { 121 226 ArrayList list = []; 122 227 flash.error = ""; 123 228 // Loop through all keys of c and remove the non-numeric ones 124 c.each { 125 if( it.key ==~ /[0-9]+/ ) { 126 def formCriterion = it.value; 229 for( c in formCriteria ) { 230 if( c.key ==~ /[0-9]+/ ) { 231 def formCriterion = c.value; 232 127 233 Criterion criterion = new Criterion(); 128 234 129 235 // Split entity and field 130 236 def field = formCriterion.entityfield?.split( /\./ ); 131 132 237 if( field.size() > 1 ) { 133 238 criterion.entity = field[0].toString(); 134 239 criterion.field = field[1].toString(); 135 240 } else { 136 criterion.entity = null; 137 criterion.field = field; 241 criterion.entity = field[0]; 242 criterion.field = null; 243 } 244 245 // Convert operator string to Operator-enum field 246 try { 247 criterion.operator = Criterion.parseOperator( formCriterion.operator ); 248 } catch( Exception e) { 249 println "Operator " + formCriterion.operator + " could not be parsed: " + e.getMessage(); 250 flash.error += "Criterion could not be used: operator " + formCriterion.operator + " is not valid.<br />\n"; 251 continue; 138 252 } 139 253 140 // Convert operator string to Operator-enum field 141 switch( formCriterion.operator ) { 142 case ">=": criterion.operator = Operator.gte; break; 143 case ">": criterion.operator = Operator.gt; break; 144 case "<": criterion.operator = Operator.lte; break; 145 case "<=": criterion.operator = Operator.lt; break; 146 case "contains": criterion.operator = Operator.contains; break; 147 case "equals": criterion.operator = Operator.equals; break; 254 // Special case of the 'in' operator 255 if( criterion.operator == Operator.insearch ) { 256 Search s 257 try { 258 s = retrieveSearch( Integer.parseInt( formCriterion.value ) ); 259 } catch( Exception e ) {} 260 261 if( !s ) { 262 flash.error += "Can't search within previous query: query not found"; 263 continue; 264 } 265 266 if( parseSearchIds ) { 267 criterion.value = s 268 } else { 269 criterion.value = s.id 270 } 271 } else { 272 // Copy value 273 criterion.value = formCriterion.value; 148 274 } 149 275 150 // Copy value151 criterion.value = formCriterion.value;152 153 276 list << criterion; 154 277 } 155 278 } 156 279 157 280 return list; 158 281 } 159 282 160 283 /** 161 284 * Returns all entities for which criteria can be entered … … 165 288 return [ 'Study', 'Subject', 'Sample', 'Event', 'SamplingEvent', 'Assay' ] 166 289 } 167 168 /** 169 * Creates an object of the given entity. 170 * 171 * @return False if the entity is not a subclass of TemplateEntity 172 */ 173 protected def getEntity( entityName ) { 174 // Find the templates 175 def entity 176 try { 177 entity = Class.forName(entityName, true, this.getClass().getClassLoader()) 178 179 // succes, is entity an instance of TemplateEntity? 180 if (entity.superclass =~ /TemplateEntity$/ || entity.superclass.superclass =~ /TemplateEntity$/) { 181 return entity; 182 } else { 183 return false; 184 } 185 } catch( ClassNotFoundException e ) { 186 log.error "Class " + entityName + " not found: " + e.getMessage() 187 return null; 188 } 189 190 } 191 290 291 /** 292 * Creates an object of the given entity. 293 * 294 * @return False if the entity is not a subclass of TemplateEntity 295 */ 296 protected def getEntity( entityName ) { 297 // Find the templates 298 def entity 299 try { 300 entity = Class.forName(entityName, true, this.getClass().getClassLoader()) 301 302 // succes, is entity an instance of TemplateEntity? 303 if (entity.superclass =~ /TemplateEntity$/ || entity.superclass.superclass =~ /TemplateEntity$/) { 304 return entity; 305 } else { 306 return false; 307 } 308 } catch( ClassNotFoundException e ) { 309 log.error "Class " + entityName + " not found: " + e.getMessage() 310 return null; 311 } 312 313 } 314 315 316 /*************************************************************************** 317 * 318 * Methods for saving results in session 319 * 320 ***************************************************************************/ 321 322 /** 323 * Saves the given search in session. Any search with the same criteria will be overwritten 324 * 325 * @param s Search to save 326 * @return Id of the search for later reference 327 */ 328 protected int saveSearch( Search s ) { 329 if( !session.queries ) 330 session.queries = [:] 331 332 // First check whether a search with the same criteria is already present 333 def previousSearch = retrieveSearchByCriteria( s.getCriteria() ); 334 335 def id 336 if( previousSearch ) { 337 id = previousSearch.id; 338 } else { 339 // Determine unique id 340 id = ( session.queries*.key.max() ?: 0 ) + 1; 341 } 342 343 s.id = id; 344 session.queries[ id ] = s; 345 346 println "On saveSearch: " + session.queries; 347 return id; 348 } 349 350 /** 351 * Retrieves a search from session with the same criteria as given 352 * @param criteria List of criteria to search for 353 * @return Search that has this criteria, or null if no such search is found. 354 */ 355 protected Search retrieveSearchByCriteria( List criteria ) { 356 if( !session.queries ) 357 return null 358 359 if( !criteria ) 360 return null 361 362 for( query in session.queries ) { 363 def key = query.key; 364 def value = query.value; 365 366 if( value.criteria && value.criteria.containsAll( criteria ) && criteria.containsAll( value.criteria ) ) { 367 return value; 368 } 369 } 370 371 return null; 372 } 373 374 375 /** 376 * Retrieves a search from session 377 * @param id Id of the search 378 * @return Search that belongs to this ID or null if no search is found 379 */ 380 protected Search retrieveSearch( int id ) { 381 if( !session.queries || !session.queries[ id ] ) 382 return null 383 384 if( !( session.queries[ id ] instanceof Search ) ) 385 return null; 386 387 println "On retrieveSearch: " + session.queries; 388 return (Search) session.queries[ id ] 389 } 390 391 /** 392 * Removes a search from session 393 * @param id Id of the search 394 * @return Search that belonged to this ID or null if no search is found 395 */ 396 protected Search discardSearch( int id ) { 397 if( !session.queries || !session.queries[ id ] ) 398 return null 399 400 def sessionSearch = session.queries[ id ]; 401 402 session.queries.remove( id ); 403 404 println "On discardSearch: " + session.queries; 405 if( !( sessionSearch instanceof Search ) ) 406 return null; 407 408 return (Search) sessionSearch 409 } 410 411 /** 412 * Retrieves a list of searches from session 413 * @return List of searches from session 414 */ 415 protected List listSearches() { 416 if( !session.queries ) 417 return [] 418 419 return session.queries*.value.toList() 420 } 192 421 }
Note: See TracChangeset
for help on using the changeset viewer.