jastrachan | 13 May 21:01 2004

Re: [groovy-dev] patch for Object.eachPropertyName()

On 13 May 2004, at 18:09, John Stump wrote:

> Hi James,
> I believe I understand what you are looking for in
> eachProperty(). I agree that your first version to get the value
> of the property is a little un-groovy, so I would like to
> propose your wrapper object idea. I can add a
> MetaClass.getMetaProperties() method which returns a collection
> of GroovyProperty objects.

How's about.

MetaClass.getProperties() returns a list of MetaProperty instances. 
e.g. right now we've got MetaClass.getMethods() which returns 

Then on the bean, if we call the properties() method, we get a list of 
GroovyProperty objects as you suggest. (BTW how about the name, 
PropertyValue as the type? As its kinda like caching the value of a 
property (albeit the value can be lazily evaluated).

> This new GroovyProperty class could
> look something like this:
> // this is a runtime representation of a property, complete
> // with descriptor and a value
> class GroovyProperty {
>    Object bean; // the owner of the property
>    PropertyDescriptor pd; // the description of the prop
>    GroovyProperty(Object bean, PropertyDescriptor pd) {
>       ...
>    }
>    String getName() {/*delegate to propertydescriptor*/ }
>    Class getType() {/*delegate to propertydescriptor*/}
>    Object getValue() {/*query bean for it*/}
> }

Yep. Though we can actually use the MetaProperty instance we've got 
already to delegate to.

> Does this look about right?


>  Would the value of the property be
> read only, or should we allow the user to modify the value
> through this mechanism? For example:

Allow it to be mutable.

> // reset all the booleans to false (stupid example, I know)
> mybean.eachProperty { if(it.type == Boolean) it.value = false }


> As for the properties() method idea, if I change the above new
> method to getProperties() and make it public, doesn't this mean
> we can treat the properties list as a property itself? So we can
> get rid of the parens (property access instead of a method
> call):
> mybean.properties.findAll { ... }
> We could even make use the cool GPath stuff:
> println mybean.properties.name

We absolutely could do that; my reservation, and the reason I suggested 
using properties() instead, was clashing with an existing property 
called 'properties'. e.g. it seems quite common to have a bean with a 
java.util.Properties object as a bean property.

With Java 2 Collections, all the APIs take non-bean names, like 
iterator(), entrySet(), values() and so forth. e.g. we may have a bean 
with a size property and collections have a size() method. So we can 
differentiate between

// the number of customers

// a list of all of the customer.size values

// which is equivalent to
customers.collect { it.size }

So I thought following the Java 2 Collections naming convention of 
properties() would mean it wouldn't clash with a property called 

e.g. consider this bean...

class ServiceBean {
     String name
     Properties properties
     boolean running

we could do

// get the properties object (java.util.Properties)
p = bean.properties

// get the list of bean property values
bean.properties().each { if (it.value instanceof String) { it.value = 
it.value + " updated!" } }