Add static iterator() methods to classes

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Add static iterator() methods to classes

Felix Dorner
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.
Reply | Threaded
Open this post in threaded view
|

Re: Add static iterator() methods to classes

OCsite
Felix,

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

On 3. 6. 2020, at 10:00 AM, Felix Dorner <[hidden email]> 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