You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@groovy.apache.org by Felix Dorner <fe...@gmail.com> on 2020/06/03 08:00:22 UTC

Add static iterator() methods to classes

Hi,

I found that if I add a static iterator() method to a class:

MyClass.class.metaClass.static[iterator] = { calculateTheIterator() }

I can use MyClass.each/grep and all these wonderful groovy methods. This is
for an EMF data model, where users often want to know stuff about objects
of a certain type in their model.

Now, obviously calculateTheIterator() needs some magic. What I currently do
is I wrap things into a closure:

withContext(context) {
   SomeClass.each { ... } SomeOtherClass.grep { }
}

the withContext method writes the context into a global static field
somewhere, and the calculateTheIterator() method just reads that value and
uses it to calculate the result using domain-specific knowledge. I wonder
if there is a way to avoid that global static variable.

Another question I have is, that I currently add the static iterator to ALL
classes of my domain separately:

    for (Class c : allTheClasses) {
         c.metaClass.static[iterator] = { calculateTheIterator () }
    }

Is there a better way to do this?


Thanks,
Felix

-- 
Linux. The choice of a GNU generation.

Re: Add static iterator() methods to classes

Posted by "ocs@ocs.cz" <oc...@ocs.cz>.
Felix,

I am not sure whether I understand properly the question, but if so...

> On 3. 6. 2020, at 10:00 AM, Felix Dorner <fe...@gmail.com> wrote:
> I found that if I add a static iterator() method to a class:
> 
> MyClass.class.metaClass.static[iterator] = { calculateTheIterator() }
> 
> I can use MyClass.each/grep and all these wonderful groovy methods. This is for an EMF data model, where users often want to know stuff about objects of a certain type in their model.
> 
> Now, obviously calculateTheIterator() needs some magic. What I currently do is I wrap things into a closure:
> 
> withContext(context) {
>    SomeClass.each { ... } SomeOtherClass.grep { }  
> }
> 
> the withContext method writes the context into a global static field somewhere, and the calculateTheIterator() method just reads that value and uses it to calculate the result using domain-specific knowledge. I wonder if there is a way to avoid that global static variable.

... well, presumed, as the example above suggests, the iterators are used only in the same thread where the context is defined, then you might consider the thread local storage (I presume ThreadLocal would be the proper solution in pure Java; myself, I use ERXThreadStorage of the Wonder library), which would work for you essentially same way as the static variable, without the danger that more different threads would clash for the static variable with potentially disastrous results.

Aside of that it might be possible to exploit the try-with-resource block, too — if there is a way to determine which objects are guarded by the thing. Which happens to be one of those things I could use myself, but can't find an answer so far; compare please my previous message in this list :)

> Another question I have is, that I currently add the static iterator to ALL classes of my domain separately:
> 
>     for (Class c : allTheClasses) {
>          c.metaClass.static[iterator] = { calculateTheIterator () }
>     }
>  
> Is there a better way to do this?

It might work if you set up the iterator for Object only with ExpandoMetaClass.enableGlobally() set (plus a reasonable default behaviour for all the other classes). No guarantee tho :)

All the best,
OC