I am working on building createCriteria
dynamically. So far so good:
obj
is the domain object I want to return
rulesList
is a list of cards in which to search by the desired field, the operator used and the value to search by
def c = obj.createCriteria() l = c.list (max: irows, offset: offset) { switch(obj){ //constrain results to those relevant to the user case Vehicle: eq("garage", usersGarage) break case Garage: users { idEq(user.id) } break } rulesList.each { rule -> switch(rule['op']){ case 'eq': eq("${rule['field']}", rule['value']) break case 'ne': ne("${rule['field']}", rule['value']) break case 'gt': gt("${rule['field']}", rule['value']) break; case 'ge': ge("${rule['field']}", rule['value']) break case 'lt': lt("${rule['field']}", rule['value']) break case 'le': le("${rule['field']}", rule['value']) break case 'bw': ilike("${rule['field']}", "${rule['value']}%") break case 'bn': not{ilike("${rule['field']}", "${rule['value']}%")} break case 'ew': ilike("${rule['field']}", "%${rule['value']}") break case 'en': not{ilike("${rule['field']}", "%${rule['value']}")} break case 'cn': ilike("${rule['field']}", "%${rule['value']}%") break case 'nc': not{ilike("${rule['field']}", "%${rule['value']}%")} break } } } }
The above code works fine and is only a little verbose with switch statements. But what if I want to add functionality to select ANY of the rules, or ALL of them? I need to conditionally put the rules in or{}
. I can not do something like
if(groupOp == 'or'){ or{ }
before going through the rules list and then
if(groupOp == 'or'){ } }
thereafter. All I can do is repeat the code for each condition:
if(groupOp == 'or'){ or{ rulesList.each { rule -> switch(rule['op']){ ... } } } } else{ rulesList.each { rule -> switch(rule['op']){ ... } }
Now the code looks pretty messy and repetitive. Suppose I want to search for a property of a property of a domain object? (For example: I want to return cars whose tires are a certain brand: vehicle.tires.brand or cars whose drivers match the name; vehicle.driver.name). Should I do something like:
switch(rule['op']){ case 'eq': switch(thePropertiesProperty){ case Garage: garage{ eq("${rule['field']}", rule['value']) } break case Driver: driver{ eq("${rule['field']}", rule['value']) } break } break case 'ne': ... }