Changeset 1424

Show
Ignore:
Timestamp:
21-01-11 16:30:04 (3 years ago)
Author:
robert@…
Message:

Improved querying and created a possibility to search for assays

Location:
trunk
Files:
6 added
4 removed
11 modified

Legend:

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

    r1415 r1424  
    3636                // Create a search object and let it do the searching 
    3737                Search search; 
     38                String view; 
    3839                switch( params.entity ) { 
    39                         case "Study":   search = new StudySearch();             break; 
    40                         case "Sample":  search = new SampleSearch();    break; 
     40                        case "Study":   search = new StudySearch();             view = "studyresults";  break; 
     41                        case "Sample":  search = new SampleSearch();    view = "sampleresults"; break; 
    4142                         
    4243                        // This exception will only be thrown if the entitiesToSearchFor contains more entities than  
     
    4748                search.execute( parseCriteria( params.criteria ) ); 
    4849                 
    49                 render( view: search.getView(), model: [search: search] ); 
     50                render( view: view, model: [search: search] ); 
    5051        } 
    5152         
     
    6465                                def templateFields = TemplateField.findAllByEntity( entity ) 
    6566                                 
    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                                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] }; 
    6770                        } 
    6871                } 
     
    8689         *      ] 
    8790         * 
    88          * @return      List with [entity: ..., field: ..., entityfield: ..., operator: ..., value: ...] tuples. 
     91         * @return      List with Criterion objects 
    8992         */ 
    9093        protected List parseCriteria( def c ) { 
     
    9497                c.each { 
    9598                        if( it.key ==~ /[0-9]+/ ) { 
    96                                 def criterium = it.value; 
     99                                def formCriterion = it.value; 
     100                                Criterion criterion = new Criterion(); 
    97101                                 
    98                                 def field = criterium.entityfield?.split( /\./ ); 
     102                                // Split entity and field 
     103                                def field = formCriterion.entityfield?.split( /\./ ); 
    99104                                 
    100105                                if( field.size() > 1 ) { 
    101                                         criterium.entity = field[0].toString(); 
    102                                         criterium.field = field[1].toString(); 
     106                                        criterion.entity = field[0].toString(); 
     107                                        criterion.field = field[1].toString(); 
    103108                                } else { 
    104                                         criterium.entity = null; 
    105                                         criterium.field = field; 
     109                                        criterion.entity = null; 
     110                                        criterion.field = field; 
    106111                                } 
    107112                                 
    108                                 list << criterium; 
     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; 
    109127                        } 
    110128                } 
  • trunk/grails-app/domain/dbnp/studycapturing/RelTime.groovy

    r959 r1424  
    2121package dbnp.studycapturing 
    2222 
    23 class RelTime { 
     23class RelTime implements Comparable { 
    2424        final static long s = 1L; 
    2525        final static long m = 60L * s; 
     
    285285 
    286286        public void computeDifference(Date start, Date end) { 
    287                 println([start, end]); 
    288                 println([start.getTime(), end.getTime()]); 
    289  
    290287                if (start && end) { 
    291288                        long seconds = (end.getTime() - start.getTime()) / 1000L; 
     
    301298                return reltime; 
    302299        } 
     300         
     301        public boolean equals( Object o ) { 
     302                if( o == null ) 
     303                        return false 
     304                if( !( o instanceof RelTime ) )  
     305                        return false 
     306                 
     307                RelTime rt = (RelTime) o; 
     308                 
     309                return rt.reltimeValue == this.reltimeValue; 
     310        } 
     311         
     312        public int compareTo( Object o ) throws ClassCastException { 
     313                if( o == null || !( o instanceof RelTime ) ) 
     314                        throw new ClassCastException( "Can't cast object " + o + " of class " + o.class.getName() + " to RelTime for comparison.") 
     315                 
     316                RelTime rt = (RelTime) o; 
     317                 
     318                return rt.reltimeValue <=> this.reltimeValue; 
     319        } 
    303320} 
  • trunk/grails-app/views/advancedQuery/index.gsp

    r1415 r1424  
    1313<form id="input_criteria"> 
    1414        <h2>Add criterium</h2> 
     15        <p> 
     16                N.B. Comparing numerical values is done without taking into 
     17                account the units. E.g. a weight of 1 kg equals 1 grams. 
     18        </p> 
    1519        <label for="field">Field</label> 
    1620                <select name="field"> 
     
    2731                </select>  
    2832                 
     33        <label for="value">Comparison</label> 
     34                <select name="operator"> 
     35                        <option value="equals">Equals</option> 
     36                        <option value="contains">Contains</option> 
     37                        <option value="&gt;=">Greater than or equals</option> 
     38                        <option value="&gt;">Greater than</option> 
     39                        <option value="&lt;">Lower than</option> 
     40                        <option value="&lt;=">Lower than or equals</option> 
     41                </select>  
     42 
    2943        <label for="value">Value</label> 
    3044                <input class='text' type="text" name="value" /> 
  • trunk/grails-app/views/advancedQuery/results.gsp

    r1415 r1424  
    1515</p> 
    1616<ul id="criteria"> 
    17         <g:each in="${search.getCriteria()}" var="criterium"> 
     17        <g:each in="${search.getCriteria()}" var="criterion"> 
    1818                <li> 
    19                         <span class="entityfield">${criterium.entityfield}</span> 
    20                         <span class="operator">${criterium.operator}</span> 
    21                         <span class="value">${criterium.value}</span> 
     19                        <span class="entityfield">${criterion.entity}.${criterion.field}</span> 
     20                        <span class="operator">${criterion.operator}</span> 
     21                        <span class="value">${criterion.value}</span> 
    2222                </li> 
    2323        </g:each> 
  • trunk/grails-app/views/advancedQuery/studyresults.gsp

    r1415 r1424  
    1515</p> 
    1616<ul id="criteria"> 
    17         <g:each in="${search.getCriteria()}" var="criterium"> 
     17        <g:each in="${search.getCriteria()}" var="criterion"> 
    1818                <li> 
    19                         <span class="entityfield">${criterium.entityfield}</span> 
    20                         <span class="operator">${criterium.operator}</span> 
    21                         <span class="value">${criterium.value}</span> 
     19                        <span class="entityfield">${criterion.entity}.${criterion.field}</span> 
     20                        <span class="operator">${criterion.operator}</span> 
     21                        <span class="value">${criterion.value}</span> 
    2222                </li> 
    2323        </g:each> 
  • trunk/src/groovy/dbnp/query/SampleSearch.groovy

    r1415 r1424  
    1515package dbnp.query 
    1616 
     17import java.util.List; 
     18import dbnp.studycapturing.*; 
     19 
    1720class SampleSearch extends Search { 
    1821        public SampleSearch() { 
     
    2124 
    2225        /** 
    23          * Executes a search based on the given criteria. Should be filled in by 
    24          * subclasses searching for a specific entity 
     26         * Searches for samples based on the given criteria. All criteria have to be satisfied and  
     27         * criteria for the different entities are satisfied as follows: 
     28         *  
     29         *              Sample.title = 'abc'             
     30         *                              Only samples are returned from studies with title 'abc' 
     31         *               
     32         *              Subject.species = 'human' 
     33         *                              Only samples are returned from subjects with species = 'human'   
     34         *  
     35         *              Sample.name = 'sample 1' 
     36         *                              Only samples are returned with name = 'sample 1' 
     37         *  
     38         *              Event.startTime = '0s' 
     39         *                              Only samples are returned from subjects that have had an event with start time = '0s'   
     40         *  
     41         *              SamplingEvent.startTime = '0s' 
     42         *                              Only samples are returned that have originated from a sampling event with start time = '0s'   
     43         *  
     44         *              Assay.module = 'metagenomics' 
     45         *                              Only samples are returned that have been processed in an assay with module = metagenomics   
     46         *  
     47         * When searching for more than one criterion per entity, these are taken combined. Searching for 
     48         *  
     49         *              Subject.species = 'human' 
     50         *              Subject.name = 'Jan' 
     51         *  
     52         *  will result in all samples from a human subject named 'Jan'. Samples from a mouse subject  
     53         *  named 'Jan' or a human subject named 'Kees' won't satisfy the criteria.  
     54         *       
    2555         */ 
    2656        @Override 
    2757        void execute() { 
     58                // TODO: check for authorization for these studies? 
     59 
     60                // If no criteria are found, return all samples 
     61                if( !criteria || criteria.size() == 0 ) { 
     62                        results = Sample.list(); 
     63                        return; 
     64                } 
     65 
     66                // We expect the sample criteria to be the most discriminative, and discard 
     67                // the most samples. (e.g. by searching on sample title of sample type). For 
     68                // that reason we first look through the list of studies. However, when the 
     69                // user didn't enter any sample criteria, this will be an extra step, but doesn't 
     70                // cost much time to process. 
     71                def samples = [] 
     72                if( getEntityCriteria( 'Study' ).size() > 0 ) { 
     73                        def studies = Study.findAll(); 
     74                        if( studies.size() == 0 ) { 
     75                                results = []; 
     76                                return; 
     77                        } 
     78                        studies = filterOnStudyCriteria( studies ); 
     79                         
     80                        def c = Sample.createCriteria() 
     81                        samples = c.list { 
     82                                'in'( 'parent', studies ) 
     83                        } 
     84                } else { 
     85                        Sample.findAll().each { 
     86                                samples << it; 
     87                        } 
     88                } 
     89 
     90                samples = filterOnSubjectCriteria( samples ); 
     91                samples = filterOnSampleCriteria( samples ); 
     92                samples = filterOnEventCriteria( samples ); 
     93                samples = filterOnSamplingEventCriteria( samples ); 
     94                samples = filterOnAssayCriteria( samples ); 
     95 
     96                // Save matches 
     97                results = samples; 
     98        } 
     99 
     100        /** 
     101         * Filters the given list of samples on the sample criteria 
     102         * @param samples       Original list of samples 
     103         * @return                      List with all samples that match the Sample-criteria 
     104         */ 
     105        protected List filterOnStudyCriteria( List studies ) { 
     106                return filterEntityList( studies, getEntityCriteria( 'Study' ), { study, criterion -> 
     107                        return criterion.matchOne( study ); 
     108                }); 
     109        } 
     110 
     111        /** 
     112         * Filters the given list of samples on the subject criteria 
     113         * @param samples       Original list of samples 
     114         * @return                      List with all samples that match the Subject-criteria 
     115         */ 
     116        protected List filterOnSubjectCriteria( List samples ) { 
     117                return filterEntityList( samples, getEntityCriteria( 'Subject' ), { sample, criterion -> 
     118                        if( !sample.parentSubject ) 
     119                                return false 
     120 
     121                        return criterion.matchOne( sample.parentSubject ); 
     122                }); 
     123        } 
     124 
     125        /** 
     126         * Filters the given list of samples on the sample criteria 
     127         * @param samples       Original list of samples 
     128         * @return                      List with all samples that match the sample-criteria 
     129         */ 
     130        protected List filterOnSampleCriteria( List samples ) { 
     131                return filterEntityList( samples, getEntityCriteria( 'Sample' ), { sample, criterion -> 
     132                        if( !sample  ) 
     133                                return false 
     134 
     135                        return criterion.matchOne( sample ); 
     136                }); 
     137        } 
     138 
     139        /** 
     140         * Filters the given list of samples on the event criteria 
     141         * @param samples       Original list of samples 
     142         * @return                      List with all samples that match the event-criteria 
     143         */ 
     144        protected List filterOnEventCriteria( List samples ) { 
     145                return filterEntityList( samples, getEntityCriteria( 'Event' ), { sample, criterion -> 
     146                        if( !sample || !sample.parentEventGroup || !sample.parentEventGroup.events?.size() ) 
     147                                return false 
     148 
     149                        return criterion.matchAny( sample.parentEventGroup.events ); 
     150                }); 
     151        } 
     152 
     153        /** 
     154         * Filters the given list of samples on the sampling event criteria 
     155         * @param samples       Original list of samples 
     156         * @return                      List with all samples that match the event-criteria 
     157         */ 
     158        protected List filterOnSamplingEventCriteria( List samples ) { 
     159                return filterEntityList( samples, getEntityCriteria( 'SamplingEvent' ), { sample, criterion -> 
     160                        if( !sample.parentEvent ) 
     161                                return false 
     162 
     163                        return criterion.matchOne( sample.parentEvent ); 
     164                }); 
     165        } 
     166 
     167 
     168        /** 
     169         * Filters the given list of samples on the assay criteria 
     170         * @param samples       Original list of samples 
     171         * @return                      List with all samples that match the assay-criteria 
     172         */ 
     173        protected List filterOnAssayCriteria( List samples ) { 
     174                if( !samples?.size() ) 
     175                        return []; 
     176 
     177                // There is no sample.assays property, so we have to look for assays another way: just find 
     178                // all assays that match the criteria 
     179                def assays = filterEntityList( Assay.list(), getEntityCriteria( 'Assay' ), { assay, criterion -> 
     180                        if( !assay ) 
     181                                return false 
     182 
     183                        return criterion.matchOne( assay ); 
     184                }); 
    28185                 
    29         } 
     186                // If no assays match these criteria, then no samples will match either 
     187                if( assays.size() == 0 ) 
     188                        return []; 
     189                         
     190                // Now filter the samples on whether they are attached to the filtered assays 
     191                return samples.findAll { sample -> 
     192                        if( !sample.parent ) 
     193                                return false; 
     194                         
     195                        def studyAssays = assays.findAll { it.parent.equals( sample.parent ); } 
     196                         
     197                        // See if this sample is present in any of the matching assays. If so,  
     198                        // this sample matches the criteria 
     199                        for( def assay in studyAssays ) { 
     200                                if( assay.samples?.contains( sample ) )  
     201                                        return true; 
     202                        } 
     203                         
     204                        return false; 
     205                } 
     206        } 
     207 
    30208} 
  • trunk/src/groovy/dbnp/query/Search.groovy

    r1415 r1424  
    1616package dbnp.query 
    1717 
     18import dbnp.studycapturing.RelTime 
     19import dbnp.studycapturing.TemplateEntity 
     20import dbnp.studycapturing.TemplateFieldType 
    1821import java.util.List; 
     22import java.text.DateFormat; 
     23import java.text.SimpleDateFormat 
    1924 
    2025class Search { 
     
    2328        protected List criteria; 
    2429        protected List results; 
    25         protected String view = "results"; 
    2630 
    2731        public List getCriteria() { return criteria; } 
     
    3034        public List getResults() { return results; } 
    3135        public void setResults( List r ) { results = r; } 
    32  
    33         public String getView() { return view; } 
    34         public void setView( String v) { view = v; } 
    3536 
    3637        /** 
     
    7071                return criteria?.findAll { it.entity == entity } 
    7172        } 
    72  
     73         
    7374        /** 
    74          * Filters a list with entities, based on the given criteria and a closure to check whether a criterium is matched 
     75         * Filters a list with entities, based on the given criteria and a closure to check whether a criterion is matched 
    7576         *  
    7677         * @param entities      Original list with entities to check for these criteria 
    7778         * @param criteria      List with criteria to match on 
    78          * @param check         Closure to see whether a specific entity matches a criterium. Gets two arguments: 
     79         * @param check         Closure to see whether a specific entity matches a criterion. Gets two arguments: 
    7980         *                                              element         The element to check  
    80          *                                              criterium       The criterium to check on. 
    81          *                                      Returns true if the criterium holds, false otherwise 
     81         *                                              criterion       The criterion to check on. 
     82         *                                      Returns true if the criterion holds, false otherwise 
    8283         * @return                      The filtered list of entities 
    8384         */ 
    84         protected List filterEntityList( List entities, List criteria, Closure check ) { 
     85        protected List filterEntityList( List entities, List<Criterion> criteria, Closure check ) { 
    8586                if( !entities || !criteria || criteria.size() == 0 ) { 
    8687                        return entities; 
     
    8889 
    8990                return entities.findAll { entity -> 
    90                         for( def criterium in criteria ) { 
    91                                 println "Check " + entity + " for " + criterium 
    92                                 if( !check( entity, criterium ) ) { 
     91                        for( criterion in criteria ) { 
     92                                if( !check( entity, criterion ) ) { 
    9393                                        return false; 
    9494                                } 
     
    9797                } 
    9898        } 
     99         
     100        /** 
     101         * Prepares a value from a template entity for comparison, by giving it a correct type 
     102         * 
     103         * @param value         Value of the field  
     104         * @param type          TemplateFieldType       Type of the specific field 
     105         * @return                      The value of the field in the correct entity 
     106         */ 
     107        public static def prepare( def value, TemplateFieldType type ) { 
     108                switch (type) { 
     109                        case TemplateFieldType.DATE: 
     110                                try { 
     111                                        return new SimpleDateFormat( "yyyy-MM-dd" ).parse( value ) 
     112                                } catch( Exception e ) { 
     113                                        return value.toString(); 
     114                                } 
     115                        case TemplateFieldType.RELTIME: 
     116                                try { 
     117                                        if( value instanceof Number ) { 
     118                                                return new RelTime( value ); 
     119                                        } else if( value.toString().isNumber() ) { 
     120                                                return new RelTime( Long.parseLong( value.toString() ) )  
     121                                        } else { 
     122                                                return new RelTime( value ); 
     123                                        } 
     124                                } catch( Exception e ) { 
     125                                        try { 
     126                                                return Long.parseLong( value ) 
     127                                        } catch( Exception e2 ) { 
     128                                                return value.toString(); 
     129                                        } 
     130                                } 
     131                        case TemplateFieldType.DOUBLE: 
     132                                try { 
     133                                        return Double.valueOf( value ) 
     134                                } catch( Exception e ) { 
     135                                        return value.toString(); 
     136                                } 
     137                        case TemplateFieldType.BOOLEAN: 
     138                                try { 
     139                                        return Boolean.valueOf( value ) 
     140                                } catch( Exception e ) { 
     141                                        println e.getMessage(); 
     142                                        return value.toString(); 
     143                                } 
     144                        case TemplateFieldType.LONG: 
     145                                try { 
     146                                        return Long.valueOf( value ) 
     147                                } catch( Exception e ) { 
     148                                        return value.toString(); 
     149                                } 
     150                        case TemplateFieldType.STRING: 
     151                        case TemplateFieldType.TEXT: 
     152                        case TemplateFieldType.STRINGLIST: 
     153                        case TemplateFieldType.TEMPLATE: 
     154                        case TemplateFieldType.MODULE: 
     155                        case TemplateFieldType.FILE: 
     156                        case TemplateFieldType.ONTOLOGYTERM: 
     157                        default: 
     158                                return value.toString(); 
     159                } 
    99160 
    100         /** 
    101          * Tries to match a value against a criterium and returns true if it matches 
    102          *  
    103          * @param value         Value of the field to match 
    104          * @param criterium     Criterium to match on. Should be a map with entries 'operator' and 'value' 
    105          * @return                      True iff the value matches this criterium, false otherwise 
    106          */ 
    107         protected boolean compare( def value, def criterium ) { 
    108                 switch( value.class.getName() ) { 
    109                         // TODO: Make the search capable of handle RelTime fields 
    110                         case "java.lang.Long":                  return longCompare( value, criterium ); 
    111                         case "java.lang.Double":                return doubleCompare( value, criterium ); 
    112                         case "java.lang.Boolean":               return booleanCompare( value, criterium ); 
    113                         case "java.lang.Date":                  return dateCompare( value, criterium ); 
    114                         case "AssayModule": 
    115                         case "Template": 
    116                         case "RelTime": 
    117                         case "Term": 
    118                         case "TemplateFieldListItem": 
    119                         default:                                                return stringCompare( value.toString(), criterium ); 
    120                 } 
    121         } 
    122  
    123         /** 
    124          * Tries to match a string value against a criterium and returns true if it matches 
    125          * 
    126          * @param value         String value of the field to match 
    127          * @param criterium     Criterium to match on. Should be a map with entries 'operator' and 'value' 
    128          * @return                      True iff the value matches this criterium, false otherwise 
    129          */ 
    130         protected boolean stringCompare( String value, def criterium ) { 
    131                 try { 
    132                         String stringCriterium = criterium.value.toString().trim() 
    133                         return value.trim().equals( stringCriterium ); 
    134                 } catch( Exception e ) { 
    135                         return false; 
    136                 } 
    137         } 
    138  
    139         /** 
    140          * Tries to match a date value against a criterium and returns true if it matches 
    141          *  
    142          * @param value         Date value of the field to match 
    143          * @param criterium     Criterium to match on. Should be a map with entries 'operator' and 'value' 
    144          * @return                      True iff the value matches this criterium, false otherwise 
    145          */ 
    146         protected boolean dateCompare( Date value, def criterium ) { 
    147                 try { 
    148                         Date dateCriterium = DateFormat.parse( criterium.value ); 
    149                         return value.equals( dateCriterium ); 
    150                 } catch( Exception e ) { 
    151                         return false; 
    152                 } 
    153         } 
    154  
    155         /** 
    156          * Tries to match a long value against a criterium and returns true if it matches 
    157          * 
    158          * @param value         Long value of the field to match 
    159          * @param criterium     Criterium to match on. Should be a map with entries 'operator' and 'value' 
    160          * @return                      True iff the value matches this criterium, false otherwise 
    161          */ 
    162         protected boolean longCompare( Long value, def criterium ) { 
    163                 try { 
    164                         Long longCriterium = Long.parseLong( criterium.value ); 
    165                         return value.equals( longCriterium ); 
    166                 } catch( Exception e ) { 
    167                         return false; 
    168                 } 
    169         } 
    170  
    171         /** 
    172          * Tries to match a double value against a criterium and returns true if it matches 
    173          * 
    174          * @param value         Double value of the field to match 
    175          * @param criterium     Criterium to match on. Should be a map with entries 'operator' and 'value' 
    176          * @return                      True iff the value matches this criterium, false otherwise 
    177          */ 
    178         protected boolean doubleCompare( Double value, def criterium ) { 
    179                 try { 
    180                         Double doubleCriterium = Double.parseDouble( criterium.value ); 
    181                         return value.equals( doubleCriterium ); 
    182                 } catch( Exception e ) { 
    183                         return false; 
    184                 } 
    185         } 
    186  
    187  
    188         /** 
    189          * Tries to match a boolean value against a criterium and returns true if it matches 
    190          * 
    191          * @param value         Boolean value of the field to match 
    192          * @param criterium     Criterium to match on. Should be a map with entries 'operator' and 'value' 
    193          * @return                      True iff the value matches this criterium, false otherwise 
    194          */ 
    195         protected boolean booleanCompare( Double value, def criterium ) { 
    196                 try { 
    197                         Boolean booleanCriterium = Boolean.parseBoolean( criterium.value ); 
    198                         return value.equals( booleanCriterium ); 
    199                 } catch( Exception e ) { 
    200                         return false; 
    201                 } 
    202161        } 
    203162} 
  • trunk/src/groovy/dbnp/query/StudySearch.groovy

    r1415 r1424  
    2020        public StudySearch() { 
    2121                this.entity = "Study"; 
    22                 this.view = "studyresults"; 
    2322        } 
    2423 
     
    4645         * as well belong to a mouse subject and still the study satisfies the criteria. 
    4746         *  
    48          * When searching for more than one criterium per entity, these are taken combined. Searching for 
     47         * When searching for more than one criterion per entity, these are taken combined. Searching for 
    4948         *  
    5049         *              Subject.species = 'human' 
     
    5251         *  
    5352         *  will result in all studies having a human subject named 'Jan'. Studies with only a mouse subject  
    54          *  named 'Jan' or a human subject named 'Kees' won't satisty the criteria.  
     53         *  named 'Jan' or a human subject named 'Kees' won't satisfy the criteria.  
    5554         *       
    5655         */ 
     
    7170                studies = filterOnSampleCriteria( studies ); 
    7271                studies = filterOnEventCriteria( studies ); 
     72                studies = filterOnSamplingEventCriteria( studies ); 
    7373                studies = filterOnAssayCriteria( studies ); 
    7474 
     
    8383         */ 
    8484        protected List filterOnStudyCriteria( List studies ) { 
    85                 return filterEntityList( studies, getEntityCriteria( 'Study' ), { study, criterium -> 
    86                         try { 
    87                                 return this.compare( study.getFieldValue( criterium.field ), criterium ); 
    88                         } catch( Exception e ) { 
    89                                 // An exception occurs if the given field doesn't exist. In that case, this criterium will fail. 
    90                                 // TODO: Maybe give the user a choice whether he want's to include these studies or not 
    91                                 return false; 
    92                         } 
     85                return filterEntityList( studies, getEntityCriteria( 'Study' ), { study, criterion -> 
     86                        return criterion.matchOne( study ); 
    9387                }); 
    9488        } 
     
    10094         */ 
    10195        protected List filterOnSubjectCriteria( List studies ) { 
    102                 return filterEntityList( studies, getEntityCriteria( 'Subject' ), { study, criterium -> 
     96                return filterEntityList( studies, getEntityCriteria( 'Subject' ), { study, criterion -> 
    10397                        if( !study.subjects?.size() ) 
    10498                                return false 
    10599 
    106                         for( subject in study.subjects ) { 
    107                                 try { 
    108                                         if( this.compare( subject.getFieldValue( criterium.field ), criterium ) ) { 
    109                                                 return true 
    110                                         } 
    111                                 } catch( Exception e ) { 
    112                                         // An exception occurs if the given field doesn't exist. In that case, this criterium will fail. 
    113                                         // TODO: Maybe give the user a choice whether he want's to include these studies or not 
    114                                 } 
    115                         } 
    116                          
    117                         return false; 
     100                        return criterion.matchAny( study.subjects ); 
    118101                }); 
    119102        } 
     
    125108         */ 
    126109        protected List filterOnSampleCriteria( List studies ) { 
    127                 return filterEntityList( studies, getEntityCriteria( 'Sample' ), { study, criterium -> 
     110                return filterEntityList( studies, getEntityCriteria( 'Sample' ), { study, criterion -> 
    128111                        if( !study.samples?.size() ) 
    129112                                return false 
    130113 
    131                         for( sample in study.samples ) { 
    132                                 try { 
    133                                         if( this.compare( sample.getFieldValue( criterium.field ), criterium ) ) 
    134                                                 return true 
    135                                 } catch( Exception e ) { 
    136                                         // An exception occurs if the given field doesn't exist. In that case, this criterium will fail. 
    137                                         // TODO: Maybe give the user a choice whether he want's to include these studies or not 
    138                                 } 
    139                         } 
    140                         return false; 
    141                          
     114                        return criterion.matchAny( study.samples ); 
    142115                }); 
    143116        } 
     
    149122         */ 
    150123        protected List filterOnEventCriteria( List studies ) { 
    151                 return filterEntityList( studies, getEntityCriteria( 'Event' ), { study, criterium -> 
     124                return filterEntityList( studies, getEntityCriteria( 'Event' ), { study, criterion -> 
    152125                        if( !study.events?.size() ) 
    153126                                return false 
    154127 
    155                         for( event in study.events ) { 
    156                                 try { 
    157                                         if( this.compare( event.getFieldValue( criterium.field ), criterium ) ) 
    158                                                 return true 
    159                                 } catch( Exception e ) { 
    160                                         // An exception occurs if the given field doesn't exist. In that case, this criterium will fail. 
    161                                         // TODO: Maybe give the user a choice whether he want's to include these studies or not 
    162                                 } 
    163                         } 
    164                         return false; 
     128                        return criterion.matchAny( study.events ); 
    165129                }); 
    166130        } 
    167131         
     132        /** 
     133        * Filters the given list of studies on the sampling event criteria 
     134        * @param studies        Original list of studies 
     135        * @return                       List with all studies that match the event-criteria 
     136        */ 
     137   protected List filterOnSamplingEventCriteria( List studies ) { 
     138           return filterEntityList( studies, getEntityCriteria( 'SamplingEvent' ), { study, criterion -> 
     139                   if( !study.samplingEvents?.size() ) 
     140                           return false 
     141 
     142                        return criterion.matchAny( study.samplingEvents ); 
     143           }); 
     144   } 
     145 
    168146         
    169147        /** 
     
    173151         */ 
    174152        protected List filterOnAssayCriteria( List studies ) { 
    175                 return filterEntityList( studies, getEntityCriteria( 'Assay' ), { study, criterium -> 
     153                return filterEntityList( studies, getEntityCriteria( 'Assay' ), { study, criterion -> 
    176154                        if( !study.assays?.size() ) 
    177155                                return false 
    178156 
    179                         for( assay in study.assays ) { 
    180                                 try { 
    181                                         if( this.compare( assay.getFieldValue( criterium.field ), criterium ) ) 
    182                                                 return true 
    183                                 } catch( Exception e ) { 
    184                                         // An exception occurs if the given field doesn't exist. In that case, this criterium will fail. 
    185                                         // TODO: Maybe give the user a choice whether he want's to include these studies or not 
    186                                 } 
    187                         } 
    188                         return false; 
     157                        return criterion.matchAny( study.assays ); 
    189158                }); 
    190159        } 
  • trunk/test/unit/dbnp/query/SearchTests.groovy

    r1415 r1424  
    11package dbnp.query 
    22 
     3import dbnp.studycapturing.RelTime 
     4import dbnp.studycapturing.TemplateFieldType; 
    35import grails.test.* 
    46 
     
    2022    protected void setUp() { 
    2123        super.setUp() 
     24                mockLogging( Search ); 
    2225    } 
    2326 
     
    2629    } 
    2730 
    28     void testSomething() { 
     31    void testPrepare() { 
     32                // Test prepare method for dates 
     33                Date d = Date.parse( "yyyy-MM-dd", "1982-10-21" ); 
     34                assert !d.equals( Search.prepare( "21-10-1982", TemplateFieldType.DATE ) ) 
     35                assert !d.equals( Search.prepare( "21-10-82", TemplateFieldType.DATE ) ) 
     36                assert d.equals( Search.prepare( "1982-10-21 00:00:00", TemplateFieldType.DATE ) ) 
     37                assert d.equals( Search.prepare( "1982-10-21", TemplateFieldType.DATE ) ) 
     38                 
     39                // Test prepare method for RelTime 
     40                assertEquals new RelTime( 0 ), Search.prepare( "", TemplateFieldType.RELTIME ) 
     41                assertEquals new RelTime( 3600 ), Search.prepare( "1h", TemplateFieldType.RELTIME ) 
     42                assertEquals new RelTime( 3600 ), Search.prepare( "60m", TemplateFieldType.RELTIME ) 
     43                assertEquals new RelTime( 3600 ), Search.prepare( "3600", TemplateFieldType.RELTIME ) 
     44                assertEquals "abc", Search.prepare( "abc", TemplateFieldType.RELTIME ) 
     45                 
     46                // Test prepare method for Double 
     47                assertEquals new Double( 100.1 ), Search.prepare( "100.1", TemplateFieldType.DOUBLE ) 
     48                assertEquals new Double( 0.0 ), Search.prepare( "0", TemplateFieldType.DOUBLE ) 
     49                assertEquals new Double( 100.0 ), Search.prepare( "100", TemplateFieldType.DOUBLE ) 
     50                assertEquals new Double( -100.1 ), Search.prepare( "-100.1", TemplateFieldType.DOUBLE ) 
     51                 
     52                // Test prepare method for Long 
     53                assertEquals new Long( 100 ), Search.prepare( "100", TemplateFieldType.LONG ) 
     54                assertEquals new Long( 0 ), Search.prepare( "0", TemplateFieldType.LONG ) 
     55                assertEquals new Long( -100 ), Search.prepare( "-100", TemplateFieldType.LONG ) 
     56                assertEquals "3.8", Search.prepare( "3.8", TemplateFieldType.LONG )     // Can't be parsed into long 
     57                assertEquals "4.2", Search.prepare( "4.2", TemplateFieldType.LONG )     // Can't be parsed into long 
     58                 
     59                // Test prepare method for Boolean 
     60                assertEquals Boolean.TRUE, Search.prepare( "true", TemplateFieldType.BOOLEAN ) 
     61                assertEquals Boolean.FALSE, Search.prepare( "false", TemplateFieldType.BOOLEAN ) 
     62                assertEquals Boolean.FALSE, Search.prepare( "", TemplateFieldType.BOOLEAN ) 
     63                assertEquals Boolean.FALSE, Search.prepare( "test", TemplateFieldType.BOOLEAN ) 
     64    } 
    2965 
    30     } 
    3166} 
  • trunk/web-app/css/advancedQuery.css

    r1415 r1424  
    1313#searchForm ul#criteria li:hover span { text-decoration: line-through; } 
    1414 
    15 #input_criteria { display: block; float: right; width: 250px; border: 1px solid #666; padding: 10px; } 
     15#input_criteria { display: block; float: right; width: 260px; border: 1px solid #666; padding: 10px; } 
    1616#input_criteria h2 { margin-top: 2px; margin-bottom: 8px; } 
    17 #input_criteria label { width: 70px; margin-top: 8px; } 
     17#input_criteria label { width: 80px; margin-top: 8px; } 
    1818#input_criteria input.text, #input_criteria select { width: 165px; } 
    1919#input_criteria input.button {  margin-top: 8px; } 
  • trunk/web-app/js/advancedQuery.js

    r1415 r1424  
    88        var field_descriptor = $( '#input_criteria select[name=field]' ).val(); 
    99        var value = $( '#input_criteria input[name=value]' ).val(); 
    10         var operator = 'equals'; 
     10        var operator = $( '#input_criteria select[name=operator]' ).val(); 
    1111         
    1212        // Show the title and a remove button 
     
    1919        // Clear the input form 
    2020        $( '#input_criteria select[name=field]' ).val( '' ); 
     21        $( '#input_criteria select[name=operator]' ).val( 'equals' ); 
    2122        $( '#input_criteria input[name=value]' ).val( '' ); 
    2223}