Just to capture your buzz interest, this is DSL-related! Read on …

OSGi filters are under-modelled, because they’re strings. Strings are great per se, they’re portable and very expressive – after all, source code is strings. So, strings – great, love’em. Write’em every day myself, for money, donchaknow.

But OSGi filters represent a shift of responsibility. With specifications, there’s always a specifier, a vendor, and a user. Specifications can come with reference implementations and library support, to help vendors and users. (OSGi is pretty well off in this regard, compared to e.g. Corba in its day.) But the responsibility for filter representation has been passed through the chain and squarely onto the user. The specifier and the vendor have told the user: Just give us back a string, and we’ll look at it and possibly give you an InvalidFilterException back. And yes, it’s checked, because you should be prepared being a gal (or guy) who can’t append strings together correctly.

Fortunately for the users, they’re programmers. They will say: OK then, I’ll have a computer make sure this string is right every time, OK? Just watch me catch that checked exception of yours, and rethrow it as a ThisNeverHappensError.

(I may have forgotten the precise name of the actual exception, InvalidFilterException. That’s because I rarely ever think about it anymore.)

So we should make filter classes, build instances with code, and hang them in trees. Make them print themselves to a well-formed string. Yes, this is the good old shape-draw-yourself thing that we old-hand object modellers thought was a silly example of polymorphism.

I have a small OSGi library brewing, name of vanadis. I will be referring to that from now on. The Filter interface there looks like this, in a condensed version – look up the code for the whole shebang:

interface Filter {
    Filter and(Filter... exprs);
    Filter or(Filter... exprs);
    Filter not();
    String toFilterString();
}

Then there is the Filters factory class, a classic static factory with static methods all over it. But if it had an interface, it would be:

public interface Filters {
    Filter eq(String attribute, Object... values);
    Filter approx(String attribute, Object... values);
    Filter gt(String attribute, Object... values);
    Filter lt(String attribute, Object... values);
    Filter present(String attribute);
    Filter substring(String attribute, String substring);
    Filter objectClasses(Class... objectClasses);
}

So, to create a simple filter that works well for a WerewolfKiller service:

    Filters.objectClasses(SilverBullet.class).and(Filters.isTrue("fullMoon"));

Of course, the Filter interface can host methods that move us closer to DSL land, allowing us to express things with less typing:

   objectClasses(SilverBullet.class).and("fullMoon");

The HelplessFarmer service might want to query for an experienced, yet reasonably stable WerewolfKiller service:

   objectClasses(WerewolfKillerService.class).andGt("killCount", 5).unless("psychotic");

And so on. You might have noticed I pass class objects to the factory methods, not class names. Again, this is an attempt to keep myself DRY – calling getName() on class objects should also be done only once. In this case, the Filter object does it at construction time, so the class object never “hangs” on the tree. However, if making a large, distributed application, you might need some filter creation happening in an infrastructural capacity, which is likely to be in a context where the classes aren’t visible. In that case, using strings to create filters might be the only way to go. But my experience tells me that you will, more often than not, be constructing filters in the context where the classes are known.

Building filter classes and putting them in trees is really quite simple. In my last project, I made a support class that allowed us to build strings correctly and incrementally: Each filter object would hold a legal filter string, and appending stuff like e.g. this.and(that) would simply create a new filter object, with “&(” at the head, then the strings from this and that, ended by “)” at the tail. This might be perfect for your purposes, and very simple.

In vanadis, I have the whole structure represented as a tree. Not only does this save on string garbage, the resulting structure is more pick-apart-able, one can do automated analysis etc. This can be golden if you find that filter matching is becoming a bottleneck.

These are all just ideas, and a work in progress that I hope to make use of in my current job. I’m happy to take comments and feedback if you have any, especially on making the base classes more generally usable.

Advertisements

exit(employer2)

2008-04-29

Today is my first day between jobs since, ooh, January 1, 2000, in fact – and only the second time between jobs at all – I’ve been very faithful to my second employer. I’m now joining a start-up, which is a new thing for me. 

Why am I writing this here? What do you care? Ah, the mysteries of blogospherics. 

Maybe you expected something interesting here. Got two things: I have some thoughts on the programmatic useability of OSGi service filters (or lack thereof) that I won’t tell yet, because of the second thing: I’m heading downtown to catch the Boris show quite soon. So try later.

So, the company I work for now has just been acquired, by a big player. No, not big – a very, very big player, in fact. Big enough to be their own little world. Those of you who read between the (code) lines of my previous post might guess which – or you probably already know. (I doubt anyone who doesn’t know me reads this anyway.)

For four days now, I will be a level 59 programmer – this is the initial ranking in this particular world. After that, I’m leaving to be a consultant for a company looking at OSGi technology. Once that ends, I’ll be joining a small start-up.

Hold your breath for more exciting posts on both the acquired-by-big-player scenario and the crazy-little-start-up scenario!