Saturday, February 6, 2010

One XPath to rule them all!

ABSTRACT: there's a million ways to access (data, objects, tables etc) these days and probably new ones are created every milisecond. What if we can figure out one that can be used anywhere?


Think about it!

/Universe/Planets/Planet[@name=='earth']/@position

XPath was created as a natural way to address elements in an XML document. One specifies the path - starting from the root node - to the element you are addressing. Conditions help you select the right nodes from many (lists) and you can address nodes or their attributes.

Extending it to addressing trees is strait-forward, so we can apply the same paradigm to any tree-structure, like Java beans...see for instance this Apache library: http://commons.apache.org/jxpath/

Come to think about it, all direct acyclical graphs fit in the same category...of course, with small differences: selecting an edge from among many possible types and lack of a root...so, some extensions are in order:

/Person[@name='John']/{hasFriends}Person

What hapens here is that the node of type Person that meets the criteria was selected as the start node and then the graph walk begins. From the many relationships tying humans together, the ones of type "hasFriends" are followed and not "hasChildren".

Yeah, you got it - even cycles are handled this way simply because as the path is walked, it reaches an end...

And... yeah, you got it again: UML domain model of classes with associations...it can describe any model you may use internally or present to clients...so we can handle pretty much any domain model described in an UML class diagram.

There.

I found myself needing four basic operations:
  • xpe : T - /** find one element */
  • xpl : List[T] - /** find a list of elements */
  • xpa : String - /** find one attribute */
  • xpla : List[String] - /** find a list of attributes */

For the sake of being concise, I will represent this new "data access interface"as either of the versions below (with explicit type and start node or implicit):

val me = XP[Person] xpe ("/Person[@areGroovy=='yeah, baby!']") from john
val minime = xpe ("/Person[@areGroovy=='yeah, baby!']")



So, why would this be useful?

Frankly, I'm growing old(er) and tired of all the non-sensical APIs that pop-up all the time everywhere: My application is unique! My domain model is complex! Everything could be an Object, but so what? I'm smarter! I know better!

My answer is: nope, your application's domain model is a class diagram and your actual objects thus form a graph. I don't need you to inven new ways to interact with your objects, over a million protocols and a million forms, when we can unify it all.

It's a very simple pattern. All it requires is that users understand basic modelling and the application's domain. The same expressions would be used by everyone...if not, at least the same pattern. No more gazillion interfaces and gazillion models.

Think about communication. Can be done in 2 ways:
1) blah blah blah can blah blah when blah blah and then some more blah blah
2) UML

You give me your domain model and, since you implement this simple no non-sense path-based model access, that's all I need to know. What you should focus on is documenting what the actual objects in your model: what they mean and what I can do with them once I have them.

This also enables generic graphical software creation. All I need is to have your domain model and then I can use a generic path composition tool (pick a node from a tree if you want).

It interactively explores the domain model, picking elements on the way.

In my integration work, I would love it if I didn't have to waste time writing stupidifying code over a miriad protocols just to get to what I needed.

If you're wondering how exactly the data should be accessed, we'll cover that in one of the next posts on this subject, in the mean time, take JOSH to heart: JSON, OSGI, Scala, Http...thank you, Gray Lens Man!


Enough for now - will continue soon...if you're interested and impatient, you can play with my prototype at http://github.com/razie/razbase/blob/master/src/razie/XP.scala