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

Last change on this file since 1430 was 1430, checked in by work@…, 10 years ago
  • set keyword expansion
  • Property svn:keywords set to Rev Author Date
File size: 4.8 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                String view;
39                switch( params.entity ) {
40                        case "Study":   search = new StudySearch();             view = "studyresults";  break;
41                        case "Sample":  search = new SampleSearch();    view = "sampleresults"; break;
42                       
43                        // This exception will only be thrown if the entitiesToSearchFor contains more entities than
44                        // mentioned in this switch structure.
45                        default:                throw new Exception( "Can't search for entities of type " + params.entity );   
46                }
47               
48                search.execute( parseCriteria( params.criteria ) );
49               
50                render( view: view, model: [search: search] );
51        }
52       
53        /**
54         * Returns a map of entities with the names of the fields the user can search on
55         * @return
56         */
57        protected def getSearchableFields() {
58                def fields = [:];
59               
60                getEntities().each {
61                        def entity = getEntity( 'dbnp.studycapturing.' + it );
62                       
63                        if( entity ) {
64                                def domainFields = entity.giveDomainFields();
65                                def templateFields = TemplateField.findAllByEntity( entity )
66                               
67                                def fieldNames = ( domainFields + templateFields ).collect { it.name }.unique() + 'Template'
68                               
69                                fields[ it ] = fieldNames.sort { a, b -> a[0].toUpperCase() + a[1..-1] <=> b[0].toUpperCase() + b[1..-1] };
70                        }
71                }
72               
73                return fields;
74        }
75       
76        /**
77         * Parses the criteria from the query form given by the user
78         * @param       c       Data from the input form and had a form like
79         *
80         *      [
81         *              0: [entityfield:a.b, operator: b, value: c],
82         *              0.entityfield: a.b,
83         *              0.operator: b,
84         *              0.field: c
85         *              1: [entityfield:f.q, operator: e, value: d],
86         *              1.entityfield: f.q,
87         *              1.operator: e,
88         *              1.field: d
89         *      ]
90         *
91         * @return      List with Criterion objects
92         */
93        protected List parseCriteria( def c ) {
94                ArrayList list = [];
95               
96                // Loop through all keys of c and remove the non-numeric ones
97                c.each {
98                        if( it.key ==~ /[0-9]+/ ) {
99                                def formCriterion = it.value;
100                                Criterion criterion = new Criterion();
101                               
102                                // Split entity and field
103                                def field = formCriterion.entityfield?.split( /\./ );
104                               
105                                if( field.size() > 1 ) {
106                                        criterion.entity = field[0].toString();
107                                        criterion.field = field[1].toString();
108                                } else {
109                                        criterion.entity = null;
110                                        criterion.field = field;
111                                }
112                               
113                                // Convert operator string to Operator-enum field
114                                switch( formCriterion.operator ) {
115                                        case ">=":                      criterion.operator = Operator.gte; break;
116                                        case ">":                       criterion.operator = Operator.gt;  break;
117                                        case "<":                       criterion.operator = Operator.lte; break;
118                                        case "<=":                      criterion.operator = Operator.lt;  break;
119                                        case "contains":        criterion.operator = Operator.contains; break;
120                                        case "equals":          criterion.operator = Operator.equals; break;
121                                }
122                               
123                                // Copy value
124                                criterion.value = formCriterion.value;
125                                 
126                                list << criterion;
127                        }
128                }
129               
130                return list;
131        }
132       
133        /**
134         * Returns all entities for which criteria can be entered
135         * @return
136         */
137        protected def getEntities() {
138                return [ 'Study', 'Subject', 'Sample', 'Event', 'SamplingEvent', 'Assay' ]
139        }
140       
141        /**
142        * Creates an object of the given entity.
143        *
144        * @return False if the entity is not a subclass of TemplateEntity
145        */
146   protected def getEntity( entityName ) {
147           // Find the templates
148           def entity
149           try { 
150                   entity = Class.forName(entityName, true, this.getClass().getClassLoader())
151
152                   // succes, is entity an instance of TemplateEntity?
153                   if (entity.superclass =~ /TemplateEntity$/ || entity.superclass.superclass =~ /TemplateEntity$/) {
154                           return entity;
155                   } else {
156                           return false;
157                   }
158           } catch( ClassNotFoundException e ) {
159                        log.error "Class " + entityName + " not found: " + e.getMessage()
160                        return null;
161           }
162
163   }
164
165}
Note: See TracBrowser for help on using the repository browser.