source: trunk/src/groovy/dbnp/query/Criterion.groovy @ 1482

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

Implemented saving of queries

  • Property svn:keywords set to Rev Author Date
File size: 10.8 KB
Line 
1package dbnp.query
2
3import java.text.SimpleDateFormat
4import org.dbnp.gdt.*
5import org.apache.commons.logging.LogFactory;
6
7/**
8 * Available operators for criteria
9 * @author robert
10 *
11 */
12enum Operator {
13        equals( "=" ), contains( "contains" ), gte( ">="), gt( ">" ), lte( "<=" ), lt( "<" ), insearch( "in" )
14        Operator(String name) { this.name = name }
15        private final String name;
16        public String toString() { return name }
17}
18
19/**
20 * Represents a criterion to search on
21 * @author robert
22 *
23 */
24class Criterion {
25        private static final log = LogFactory.getLog(this);
26        public String entity
27        public String field
28        public Operator operator
29        public def value
30
31        /**
32         * Retrieves a combination of the entity and field
33         * @return
34         */
35        public String entityField() {
36                return entity.toString() + ( field ? "." + field.toString() : "" );
37        }
38       
39        /**
40         * Retrieves the correct value for this criterion in the given object (with template)
41         *
42         * @param entity                Entity to check for value. Should be a child of template entity
43         * @param criterion             Criterion to match on
44         * @return                              Value of the given field or null if the field doesn't exist
45         */
46        public def getFieldValue( TemplateEntity entity ) {
47                if( entity == null )
48                        return null;
49
50                try {
51                        def fieldValue
52                        if( !field ) {
53                                fieldValue = entity
54                        } else if( field == "Template" ) {
55                                fieldValue = entity.template?.name
56                        } else {
57                                fieldValue = Search.prepare( entity.getFieldValue( field ), entity.giveFieldType( field ) )
58                        }
59
60                        return fieldValue
61                } catch( Exception e ) {
62                        // An exception occurs if the given field doesn't exist. In that case, this criterion will fail.
63                        // TODO: Maybe give the user a choice whether he want's to include these studies or not
64                        return null;
65                }
66        }
67
68        /**
69         * Checks if the given object (with template) that satisfies the given criterion.
70         *
71         * @param entity                Entity to check for criterion satisfaction. Should be a child of template entity
72         * @param criterion     Criterion to match on
73         * @return                      True iff there the entity satisfies the given criterion.
74         */
75        public boolean matchEntity( TemplateEntity entity ) {
76                def fieldValue = this.getFieldValue( entity );
77
78                // Null is returned, the given field doesn't exist. In that case, this criterion will fail.
79                // TODO: Maybe give the user a choice whether he want's to include these studies or not
80                if( fieldValue == null )
81                        return false;
82
83                return this.match( fieldValue );
84        }
85
86        /**
87         * Checks for all entities in the given entityList, if there is any object that satisfies the given criterion.
88         *
89         * @param entityList    List with entities. The entities should be child classes of TemplateEntity
90         * @param criterion             Criterion to match on
91         * @return                              True iff there is any entity in the list that satisfies the given criterion.
92         */
93        public boolean matchAnyEntity( List<TemplateEntity> entityList ) {
94                for( entity in entityList ) {
95                        if( matchOneEntity( entity ) )
96                                return true;
97                }
98                return false;
99        }
100
101        /**
102         * Checks for all entities in the given entityList, if all objects satisfy the given criterion.
103         *
104         * @param entityList    List with entities. The entities should be child classes of TemplateEntity
105         * @param criterion             Criterion to match on
106         * @return                              True iff all entities satisfy the given criterion.
107         */
108        public boolean matchAllEntities( List<TemplateEntity> entityList ) {
109                for( entity in entityList ) {
110                        if( !matchOneEntity( entity ) )
111                                return false;
112                }
113                return true;
114        }
115
116        /**
117         * Checks for all values in the given List, if there is any value that satisfies the given criterion.
118         *
119         * @param entityList            List with values.
120         * @param criterion             Criterion to match on
121         * @return                              True iff there is any value in the list that satisfies the given criterion.
122         */
123        public boolean matchAny( List valueList ) {
124                for( value in valueList ) {
125                        if( match( value ) )
126                                return true;
127                }
128                return false;
129        }
130
131        /**
132         * Checks for all values in the given List, if all values satisfy the given criterion.
133         *
134         * @param entityList            List with values.
135         * @param criterion             Criterion to match on
136         * @return                              True iff all values satisfy the given criterion.
137         */
138        public boolean matchAll( List entityList ) {
139                for( value in valueList ) {
140                        if( !match( value ) )
141                                return false;
142                }
143                return true;
144        }
145
146        /**
147         * Tries to match a value against a criterion and returns true if it matches
148         *
149         * @param value         Value of the field to match
150         * @return                      True iff the value matches this criterion, false otherwise
151         */
152        public boolean match( def fieldValue ) {
153                if( fieldValue == null )
154                        return false;
155               
156                // in-search criteria have to be handled separately
157                if( this.operator == Operator.insearch ) {
158                        return this.value?.getResults()?.contains( fieldValue );
159                }       
160               
161                // Other criteria are handled based on the class of the value given.
162                def classname = fieldValue.class.getName();
163                classname = classname[classname.lastIndexOf( '.' ) + 1..-1].toLowerCase();
164
165                try {
166                        switch( classname ) {
167                                case "integer":                                 return longCompare( new Long( fieldValue.longValue() ) );
168                                case "long":                                    return longCompare( fieldValue );
169                                case "float":                                   return doubleCompare( new Long( fieldValue.doubleValue() ) );
170                                case "double":                                  return doubleCompare( fieldValue );
171                                case "boolean":                                 return booleanCompare( fieldValue );
172                                case "date":                                    return dateCompare( fieldValue);
173                                case "reltime":                                 return relTimeCompare( fieldValue );
174                                case "assaymodule":
175                                case "template":
176                                case "term":
177                                case "templatefieldlistitem":
178                                case "string":
179                                default:                                                return compareValues( fieldValue.toString().trim().toLowerCase(), this.operator, value.toString().toLowerCase().trim() );
180                        }
181                } catch( Exception e ) {
182                        log.error e.class.getName() + ": " + e.getMessage();
183                        return false;
184                }
185        }
186
187        /**
188         * Tries to match a value against a criterion and returns true if it matches
189         *
190         * @param fieldValue            Value of the field to match
191         * @param operator                      Operator to apply
192         * @param criterionValue        Value of the criterion
193         * @return                                      True iff the value matches this criterion value, false otherwise
194         */
195        protected boolean compareValues( def fieldValue, Operator operator, def criterionValue ) {
196                switch( operator ) {
197                        case Operator.gte:
198                                return fieldValue >= criterionValue;
199                        case Operator.gt:
200                                return fieldValue > criterionValue;
201                        case Operator.lt:
202                                return fieldValue < criterionValue;
203                        case Operator.lte:
204                                return fieldValue <= criterionValue;
205                        case Operator.contains:
206                                // Contains operator can only be used on string values
207                                return fieldValue.toString().contains( criterionValue.toString() );
208                        case Operator.equals:
209                        default:
210                                return fieldValue.equals( criterionValue );
211                }
212
213        }
214
215        /**
216         * Tries to match a date value against a criterion and returns true if it matches
217         *
218         * @param value         Date value of the field to match
219         * @return                      True iff the value matches this criterion, false otherwise
220         */
221        protected boolean dateCompare( Date fieldValue ) {
222                try {
223                        Date dateCriterion = new SimpleDateFormat( "yyyy-MM-dd" ).parse( value );
224                        Date fieldDate = new Date( fieldValue.getTime() );
225
226                        // Clear time in order to just compare dates
227                        dateCriterion.clearTime();
228                        fieldDate.clearTime();
229
230                        return compareValues( fieldDate, this.operator, dateCriterion )
231                } catch( Exception e ) {
232                        log.error e.class.getName() + ": " + e.getMessage();
233                        return false;
234                }
235        }
236
237        /**
238         * Tries to match a long value against a criterion and returns true if it matches
239         *
240         * @param value         Long value of the field to match
241         * @param criterion     Criterion to match on. Should be a map with entries 'operator' and 'value'
242         * @return                      True iff the value matches this criterion, false otherwise
243         */
244        protected boolean longCompare( Long fieldValue ) {
245                Long longCriterion;
246                try {
247                        longCriterion = Long.parseLong( value );
248                } catch( Exception e ) {
249                        try {
250                                // If converting to long doesn't work, try converting to double and rounding it
251                                Double doubleCriterion = Double.parseDouble(value);
252                                longCriterion = new Long( doubleCriterion.longValue() );
253                        } catch( Exception e2 ) {
254                                log.error e2.class.getName() + ": " + e2.getMessage();
255                                return false;
256                        }
257                }
258                return compareValues( fieldValue, this.operator, longCriterion );
259        }
260
261        /**
262         * Tries to match a double value against a criterion and returns true if it matches
263         *
264         * @param value         Double value of the field to match
265         * @return                      True iff the value matches this criterion, false otherwise
266         */
267        protected boolean doubleCompare( Double fieldValue ) {
268                try {
269                        Double doubleCriterion = Double.parseDouble( value );
270                        return compareValues( fieldValue, this.operator, doubleCriterion );
271                } catch( Exception e ) {
272                        log.error e.class.getName() + ": " + e.getMessage();
273                        return false;
274                }
275        }
276
277
278        /**
279         * Tries to match a boolean value against a criterion and returns true if it matches
280         *
281         * @param value         Boolean value of the field to match
282         * @return                      True iff the value matches this criterion, false otherwise
283         */
284        protected boolean booleanCompare( Boolean fieldValue ) {
285                try {
286                        Boolean booleanCriterion = Boolean.parseBoolean( value );
287                        return compareValues( fieldValue, this.operator, booleanCriterion );
288                } catch( Exception e ) {
289                        log.error e.class.getName() + ": " + e.getMessage();
290                        return false;
291                }
292        }
293
294        /**
295         * Tries to match a relTime value against a criterion and returns true if it matches
296         *
297         * @param value         relTime value of the field to match
298         * @return                      True iff the value matches this criterion, false otherwise
299         */
300        protected boolean relTimeCompare( RelTime fieldValue ) {
301                try {
302                        RelTime rt
303
304                        // Numbers are taken to be seconds, if a non-numeric value is given, try to parse it
305                        if( value.toString().isLong() ) {
306                                rt = new RelTime( Long.parseLong( value.toString() ) );
307                        } else {
308                                rt = new RelTime( value.toString() );
309                        }
310
311                        return compareValues( fieldValue, this.operator, rt );
312                } catch( Exception e ) {
313                        log.error e.class.getName() + ": " + e.getMessage();
314                        return false;
315                }
316        }
317       
318        public static Operator parseOperator( String name ) throws Exception {
319                switch( name.trim() ) {
320                        case "=": 
321                        case "equals":          return Operator.equals; 
322                        case "contains":        return Operator.contains; 
323                        case ">=": 
324                        case "gte":                     return Operator.gte; 
325                        case ">": 
326                        case "gt":                      return Operator.gt; 
327                        case "<=": 
328                        case "lte":                     return Operator.lte; 
329                        case "<": 
330                        case "lt":                      return Operator.lt; 
331                        case "in":                      return Operator.insearch;
332                        default:
333                                throw new Exception( "Operator not found" ); 
334                }
335        }
336
337        public String toString() {
338                return "[Criterion " + entityField() + " " + operator + " " + value + "]";
339        }
340       
341        public boolean equals( Object o ) {
342                if( o == null )
343                        return false;
344               
345                if( !( o instanceof Criterion ) ) 
346                        return false;
347                       
348                Criterion otherCriterion = (Criterion) o;
349                return  this.entity == otherCriterion.entity &&
350                                this.field == otherCriterion.field && 
351                                this.operator == otherCriterion.operator &&
352                                this.value == otherCriterion.value;
353        }
354}
Note: See TracBrowser for help on using the repository browser.