source: trunk/grails-app/controllers/dbnp/query/AdvancedQueryController.groovy @ 1415

Last change on this file since 1415 was 1415, checked in by robert@…, 10 years ago

First version of advanced querying

File size: 4.1 KB
Line 
1package dbnp.query
2
3import dbnp.studycapturing.*
4
5// TODO: Make use of the searchable-plugin possibilities instead of querying the database directly
6
7/**
8 * Basic web interface for searching within studies
9 *
10 * @author Robert Horlings (robert@isdat.nl)
11 */
12class AdvancedQueryController {
13        def entitiesToSearchFor = [ 'Study': 'Studies', 'Sample': 'Samples']
14    def index = {
15                [entitiesToSearchFor: entitiesToSearchFor, searchableFields: getSearchableFields()]
16    }
17
18        /**
19         * Searches for studies or samples based on the user parameters.
20         *
21         * @param       entity          The entity to search for ( 'Study' or 'Sample' )
22         * @param       criteria        HashMap with the values being hashmaps with field, operator and value.
23         *                                              [ 0: [ field: 'Study.name', operator: 'equals', value: 'term' ], 1: [..], .. ]
24         */
25        def search = {
26                if( !params.criteria ) {
27                        flash.error = "No criteria given to search for. Please try again.";
28                        redirect( action: 'index' )
29                }
30
31                if( !params.entity || !entitiesToSearchFor*.key.contains( params.entity ) ) {
32                        flash.error = "No or incorrect entity given to search for. Please try again.";
33                        redirect( action: 'index', params: [ criteria: parseCriteria( params.criteria ) ] )
34                }
35
36                // Create a search object and let it do the searching
37                Search search;
38                switch( params.entity ) {
39                        case "Study":   search = new StudySearch();             break;
40                        case "Sample":  search = new SampleSearch();    break;
41                       
42                        // This exception will only be thrown if the entitiesToSearchFor contains more entities than
43                        // mentioned in this switch structure.
44                        default:                throw new Exception( "Can't search for entities of type " + params.entity );   
45                }
46               
47                search.execute( parseCriteria( params.criteria ) );
48               
49                render( view: search.getView(), model: [search: search] );
50        }
51       
52        /**
53         * Returns a map of entities with the names of the fields the user can search on
54         * @return
55         */
56        protected def getSearchableFields() {
57                def fields = [:];
58               
59                getEntities().each {
60                        def entity = getEntity( 'dbnp.studycapturing.' + it );
61                       
62                        if( entity ) {
63                                def domainFields = entity.giveDomainFields();
64                                def templateFields = TemplateField.findAllByEntity( entity )
65                               
66                                fields[ it ] = ( domainFields + templateFields ).collect { it.name }.unique().sort { a, b -> a[0].toUpperCase() + a[1..-1] <=> b[0].toUpperCase() + b[1..-1] };
67                        }
68                }
69               
70                return fields;
71        }
72       
73        /**
74         * Parses the criteria from the query form given by the user
75         * @param       c       Data from the input form and had a form like
76         *
77         *      [
78         *              0: [entityfield:a.b, operator: b, value: c],
79         *              0.entityfield: a.b,
80         *              0.operator: b,
81         *              0.field: c
82         *              1: [entityfield:f.q, operator: e, value: d],
83         *              1.entityfield: f.q,
84         *              1.operator: e,
85         *              1.field: d
86         *      ]
87         *
88         * @return      List with [entity: ..., field: ..., entityfield: ..., operator: ..., value: ...] tuples.
89         */
90        protected List parseCriteria( def c ) {
91                ArrayList list = [];
92               
93                // Loop through all keys of c and remove the non-numeric ones
94                c.each {
95                        if( it.key ==~ /[0-9]+/ ) {
96                                def criterium = it.value;
97                               
98                                def field = criterium.entityfield?.split( /\./ );
99                               
100                                if( field.size() > 1 ) {
101                                        criterium.entity = field[0].toString();
102                                        criterium.field = field[1].toString();
103                                } else {
104                                        criterium.entity = null;
105                                        criterium.field = field;
106                                }
107                               
108                                list << criterium;
109                        }
110                }
111               
112                return list;
113        }
114       
115        /**
116         * Returns all entities for which criteria can be entered
117         * @return
118         */
119        protected def getEntities() {
120                return [ 'Study', 'Subject', 'Sample', 'Event', 'SamplingEvent', 'Assay' ]
121        }
122       
123        /**
124        * Creates an object of the given entity.
125        *
126        * @return False if the entity is not a subclass of TemplateEntity
127        */
128   protected def getEntity( entityName ) {
129           // Find the templates
130           def entity
131           try { 
132                   entity = Class.forName(entityName, true, this.getClass().getClassLoader())
133
134                   // succes, is entity an instance of TemplateEntity?
135                   if (entity.superclass =~ /TemplateEntity$/ || entity.superclass.superclass =~ /TemplateEntity$/) {
136                           return entity;
137                   } else {
138                           return false;
139                   }
140           } catch( ClassNotFoundException e ) {
141                        log.error "Class " + entityName + " not found: " + e.getMessage()
142                        return null;
143           }
144
145   }
146
147}
Note: See TracBrowser for help on using the repository browser.