Ignore:
Timestamp:
Feb 2, 2011, 4:40:22 PM (12 years ago)
Author:
robert@…
Message:

Implemented saving of queries

File:
1 edited

Legend:

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

    r1458 r1482  
    1212class AdvancedQueryController {
    1313        def moduleCommunicationService;
     14        def authenticationService
     15
     16        def entitiesToSearchFor = [ 'Study': 'Studies', 'Sample': 'Samples']
    1417       
    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        }
    1929
    2030        /**
     
    3848                // Create a search object and let it do the searching
    3949                Search search;
    40                 String view;
     50                String view = determineView( params.entity );
    4151                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
    4656                        // 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                }
    5059                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]
    53125        }
    54126       
     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
    55160        /**
    56161         * Returns a map of entities with the names of the fields the user can search on
     
    59164        protected def getSearchableFields() {
    60165                def fields = [:];
    61                
     166
    62167                // Retrieve all local search fields
    63168                getEntities().each {
    64169                        def entity = getEntity( 'dbnp.studycapturing.' + it );
    65                        
     170
    66171                        if( entity ) {
    67172                                def domainFields = entity.giveDomainFields();
    68173                                def templateFields = TemplateField.findAllByEntity( entity )
    69                                
     174
    70175                                def fieldNames = ( domainFields + templateFields ).collect { it.name }.unique() + 'Template'
    71                                
     176
    72177                                fields[ it ] = fieldNames.sort { a, b -> a[0].toUpperCase() + a[1..-1] <=> b[0].toUpperCase() + b[1..-1] };
    73178                        }
    74179                }
    75                
     180
    76181                // Loop through all modules and check which fields are searchable
    77182                // Right now, we just combine the results for different entities
     
    81186                                def json = moduleCommunicationService.callModuleRestMethodJSON( module.url, callUrl );
    82187                                def moduleFields = [];
    83                                 entitiesToSearchFor.each { entity ->                                   
     188                                entitiesToSearchFor.each { entity ->
    84189                                        if( json[ entity.key ] ) {
    85190                                                json[ entity.key ].each { field ->
     
    88193                                        }
    89194                                }
    90                                
     195
    91196                                // Remove 'module' from module name
    92197                                def moduleName = module.name.replace( 'module', '' ).trim()
    93                                
     198
    94199                                fields[ moduleName ] = moduleFields.unique();
    95200                        } catch( Exception e ) {
     
    97202                        }
    98203                }
    99                
     204
    100205                return fields;
    101206        }
    102        
     207
    103208        /**
    104209         * Parses the criteria from the query form given by the user
     
    115220         *              1.field: d
    116221         *      ]
    117          *
    118          * @return      List with Criterion objects
    119          */
    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 ) {
    121226                ArrayList list = [];
    122                
     227                flash.error = "";
    123228                // 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                               
    127233                                Criterion criterion = new Criterion();
    128                                
     234
    129235                                // Split entity and field
    130236                                def field = formCriterion.entityfield?.split( /\./ );
    131                                
    132237                                if( field.size() > 1 ) {
    133238                                        criterion.entity = field[0].toString();
    134239                                        criterion.field = field[1].toString();
    135240                                } 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;
    138252                                }
    139253                               
    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;
    148274                                }
    149275                               
    150                                 // Copy value
    151                                 criterion.value = formCriterion.value;
    152                                  
    153276                                list << criterion;
    154277                        }
    155278                }
    156                
     279
    157280                return list;
    158281        }
    159        
     282
    160283        /**
    161284         * Returns all entities for which criteria can be entered
     
    165288                return [ 'Study', 'Subject', 'Sample', 'Event', 'SamplingEvent', 'Assay' ]
    166289        }
    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        }
    192421}
Note: See TracChangeset for help on using the changeset viewer.