The multi variable seeker

To get anything done you need to find things. The normal software system has the same need. So how do we go about to declare a non limiting multi variable user friendly seeker into a generic model driven system like a WECPOF app?

This is what we need:

1. We need non rooted, persistent storage evaluated OCL expressions in order to execute a search

2. We need user input on how to limit the search

3. We need to allow for the user to use different limiting criteria’s as he or she see fit ; after all the One-Field-Matches-Everything tactic that Google use does not really cut the mustard in enterprise applications (Touching a nerve did I? Users will want to limit the search on “Only this department”, “Only things from yesterday” etc, and even in google you need to use an extended syntax to get this done).

4. We want to allow for multiple sets of search definitions per seeker interface – if the user does not get a hit using the filters with the first set, it is natural for the user to “try again” and then we want to use another set of search criteria’s; this has been tested on real users and they find it intuitive and obvious that it should work this way.

This article use this model:

image

And this is how we define the seeker:

image

#1 We declare variables that holds the user input – one variable is a string, and the other is an Object reference of type ReferenceClass (from our model).

#2 We add Columns that use these variables so that we get some UI for the user to enter the criteria’s into. The Reference value we set up as a PickList.

#3 We create a SearchExpression with two criterias – the result of the two criteria’s will be intersected (on the server side). And here is an important fact: Since the result of the criteria’s will be intersected we need some way to say if a criteria is Active or not – after all it is up to the user to limit the search on either or both of the two criteria’s.

This is how the activation of a Criteria is done:

image

and

image

The Active Expression is optional, if you leave it blank it defaults to true – always on.

#4 The second batch of search expression is executed the second time the user clicks the search button BUT only if the search variables has not changed. You can have as many search batches as you need, and they are round-robin-used whenever the user clicks the search button with untouched variables. Whenever a variable is changed the Round-robin is reset and the first batch is used again.

Even if these rules may seem complex they are intuitive for the user – especially if you use the search batches to filter for the same data as the resulting columns show. For example; the user enters someone’s first name, but your first batch filter on last name – the wrong people comes up for the first search, the user hits search again – now we use the second batch where you filter on first name – voila. This was just an example – you can just as well create a filter expression that unions the first name and the last name results ; Person.allinstances->select(a|a.FirstName.SqlLike(vSeekString+’%’))->union(Person.allinstances->select(a|a.LastName.SqlLike(vSeekString+’%’)))

Another example might be that the users enter a number – first we try to match it with a product code, user hits search again, we try to match it with the order number. The user is still not happy so he hit search again – now we match it with the phone number of the customer – user happy. In this example we could have chosen to create a detailed search interface with 3 text boxes – one for product code, one for order number and one for customer phone number – just as valid. Or we could do a union expression as above – just as valid. Choose the strategy that sits best with your users.

This entry was posted in Seeker, ViewModel. Bookmark the permalink.

2 Responses to The multi variable seeker

  1. Pingback: WECPOF Goodies 1 | CapableObjects

  2. Pingback: PSExpression , or how to do things in the DB from MDriven | CapableObjects

Leave a Reply

Your email address will not be published. Required fields are marked *

*