root/trunk/grails-app/controllers/dbnp/query/AdvancedQueryController.groovy @ 1456

Revision 1456, 4.7 KB (checked in by business@…, 3 years ago)

moved gdt package to org.dbnp, moved tests for RelTime?, TemplateEntity?, Template etc. to gdt plugin

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