<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>BlackBox : My Groovy HOM - take 2</title>
    <link>http://www.warneronstine.com/blog/articles/2007/04/27/my-groovy-hom-take-2</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Where technology and art disappear</description>
    <item>
      <title>My Groovy HOM - take 2</title>
      <description>&lt;p&gt;Alright, so I lied. I decided to use this example elsewhere and definitely needed something more flexible. So I spent a couple of hours (and one weird Groovy compilation bug later) and got my HOM implementation so that it uses closures to find stuff. It still uses &lt;code&gt;findAll&lt;/code&gt;, but now it makes the determination from the closure passed into it. Now, theoretically you can implement any &amp;#8220;message&amp;#8221; you want and associate it with a closure in &lt;code&gt;ArrayListMetaClass&lt;/code&gt; and voila you have a new operator for any collection. Of course HOM should be more flexible as well, but that I will leave up to others as far as implementation (unless the bug bites me again and I want to expand it a bit more).&lt;/p&gt;

&lt;p&gt;Here then is the new relevant code for &lt;code&gt;ArrayListMetaClass&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def whereClosure = { method, args, item -&amp;gt;
    List list = InvokerHelper.asList(args);
    if(list.size() == 0) {
        if( item."${method}"() ) {
            return item
        }
    } else {
        if( item."${method}"(args) ) {
            return item
        }
    }
}

def unlessClosure = { method, args, item -&amp;gt;
    List list = InvokerHelper.asList(args);
    if(list.size() == 0) {
        if(!item."${method}"() ) {
            return item
        }
    } else {
        if(!item."${method}"(args) ) {
            return item
        }
    }
}

def queryTypes = ['where': whereClosure, 'unless': unlessClosure]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#8230;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def Object getProperty(Object obj, String prop) {
    if(queryTypes.containsKey(prop)) {
        this.hom = new HigherOrderMessage(obj, queryTypes.get(prop))
        return this.hom
    } else {
        return super.getProperty(obj, prop);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So, the new items that you&amp;#8217;ll notice here is that I decided to go with the closure idea and created two new closures. The &lt;code&gt;whereClosure&lt;/code&gt; takes three arguments, the method we&amp;#8217;re calling, the arguments to that method and the actual item that needs to get called. Here&amp;#8217;s what happens when this closure gets passed in to the HOM object:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def Object invokeMethod(String methodName, arguments) {
    def closure = this.prop.curry(methodName, arguments)
    return this.object.findAll(closure)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What we are doing is currying the closure that was passed in and setting the method name and arguments (as they are passed in to &lt;code&gt;invokeMethod&lt;/code&gt;) and then passes the curried closure into the &lt;code&gt;findAll()&lt;/code&gt; method. Of course I&amp;#8217;ve added in a new unit test as well to test my new &lt;code&gt;unlessClosure&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    newList = list.unless.retired()
    assert newList.size() == 3
    assert newList == nonRetiredCollection()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, if you want the code, you can &lt;a href="http://www.warneronstine.com/download/hom-groovy2.tgz"&gt;grab it here&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 27 Apr 2007 18:26:16 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:844f69f8-6a9d-47da-888f-9abdb9cb8d9d</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2007/04/27/my-groovy-hom-take-2</link>
      <category>programming</category>
      <category>groovy</category>
      <category>dsl</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/289</trackback:ping>
    </item>
  </channel>
</rss>
