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

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

Made querying aware of the templates being moved to a plugin. Also added imports of the plugin objects in some integration tests (see #225)

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