[ 
https://issues.apache.org/jira/browse/GROOVY-10392?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17469459#comment-17469459
 ] 

William Woodman commented on GROOVY-10392:
------------------------------------------

eric - had a go at trying to figure this out - but its tough going.  

 

however i think the problem *starts* in the internal class returned from 
calling metaClass.static.  This returns a instance of 

protected class ExpandoMetaProperty, where the propertyName has been set to 
'static'.

 

however if look at the methods on this class, it only processes (not static)  
closures via the leftShift() method and then just provides a getProperty and 
setProperty as follows 

 
{code:java}
public Object leftShift(Object arg) {
    registerIfClosure(arg, false);  //private method called 
    return this;
}

//...
@Override
/** NB this is kinda useless if the property doesnt exist - it just returns 
ExpandoMetaProperty with propertyName set yo whatever you put in !

 public Object getProperty(String property) {
    this.propertyName = property;
    return this;
}

/* (non-Javadoc)
   * @see groovy.lang.GroovyObjectSupport#setProperty(java.lang.String, 
java.lang.Object)
   */

@Override
public void setProperty(String property, Object newValue) {
    this.propertyName = property;
    registerIfClosure(newValue, true);
} {code}
 

The getProperty() is pretty useless - see comment in code above 

you'll note that if the value on the setProperty() is closure it has a go at 
registering that tries to registerStatic, else tries registerInstance.

 

the leftshift() action only builds a non static entry (which itself is kinda 
weird as metaClass.static items should be static by default?

 

There is no registerStaticProperty (property, newValue) *method* here at all - 
this is why 

 
{code:java}
metaClass.'static'.statProp = "some value" 
{code}
 

 

just gets quietly swallowed and does nothing 

 

what you want is something like registerStaticBeanProperty (property, value) - 
but you look at the code for existing registerBeanProperty and it generates  
new ThreadManagedMetaBeanProperty as the returned MetaBeanProperty.  Problem 
with this is there is no way to set the modifiers to be static.  The words say 
the modifiers are inferred from the getters/setters used.  but they are not 
part of the constructor signature!  

 

what you sort of want is a ThreadManaged{*}Static{*}MetaBeanProperty which does 
this for you automatically.  if you look at the existing *non static* version 
(below) it ends up just putting the generated mbp into the  expandoProperties 
map field  , and the getters/setter get added to the expandoMethods map field 

 

 
{code:java}
public void registerBeanProperty(final String property, final Object newValue) {
        performOperationOnMetaClass(() -> {
            Class type = newValue == null ? Object.class : newValue.getClass();
            MetaBeanProperty mbp = newValue instanceof MetaBeanProperty ? 
(MetaBeanProperty) newValue : new ThreadManagedMetaBeanProperty(theClass, 
property, type, newValue);
            final MetaMethod getter = mbp.getGetter();
            final MethodKey getterKey = new DefaultCachedMethodKey(theClass, 
getter.getName(), CachedClass.EMPTY_ARRAY, false);
            final MetaMethod setter = mbp.getSetter();
            final MethodKey setterKey = new DefaultCachedMethodKey(theClass, 
setter.getName(), setter.getParameterTypes(), false);
            addMetaMethod(getter);
            addMetaMethod(setter);            
            expandoMethods.put(setterKey, setter);
            expandoMethods.put(getterKey, getter);
            expandoProperties.put(mbp.getName(), mbp); 
            addMetaBeanProperty(mbp);
            performRegistryCallbacks();
        });
    } {code}
 

 

i've kind of ground to halt today as there is no existing impl subclass of 
MetaBeanProperty that seems to readily set the static modifiers for you 

 

However i think this is the starting point of most of the problems 

 

in a script i've tried to look at the metaClass expandoProperties, and methods 
- like this and when you look at the results there are some static props and 
methods in the list arriving via other means 

 

 
{code:java}
//...in script 

class WillsClass {
    String prop = "class property"

    static String sprop = "static class property "
}


//.....
String modType (int mod) {  //helper class
    if (Modifier.isStatic(mod))
        return "static"
    if (Modifier.isPublic(mod))
        return "public"
    if (Modifier.isProtected(mod))
        return "protected"
    if (Modifier.isPrivate(mod))
        return "private"
}


Collection props = 
wo.metaClass.getExpandoProperties().collect{"name:${it.name}, 
mod:${modType(it.modifiers)}"}
Collection meths = wo.metaClass.getMethods().collect{"name:${it.name}, 
mod:${modType(it.modifiers)}"}

 {code}
 when you look at the static sprop above you can see entries for 
"name:getSprop, mod:static", and name:setSprop, mod:static" in the methods, 

 

but there is no static property for sprop in ExpandoProperties (presumably as 
its declared directly in the class ) 

 

 

 

 

 

> Inconsistent metaClass capability for .static properties and methods vs 
> ordinary dynamic properties and methods  
> -----------------------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-10392
>                 URL: https://issues.apache.org/jira/browse/GROOVY-10392
>             Project: Groovy
>          Issue Type: Improvement
>          Components: Compiler
>    Affects Versions: 3.0.9, 4.0.0-beta-2
>            Reporter: William Woodman
>            Priority: Minor
>             Fix For: 3.x, 4.x
>
>
> runtime addition and working with static dynamic properties and methods is 
> inconsistent and doesnt work the same as the equivalent capability for 
> ordinary dynamic properties and methods.
> I've tried to show the problem in the script code below 
> {code:groovy}
> package script
> class SomeClass {
> static String classDeclaredStatName = "in class definition static name"
> String name = "instance level name"
> }
> //add a new property to metaclass - works fine
> SomeClass.metaClass.dynProp = "dynamic property added"
> SomeClass.metaClass.dynMethod = \{"dynamic method added as closure"}
> SomeClass.metaClass.static.dynStaticProp = "dynamic static property added"
> SomeClass.metaClass.static.dynStaticMethod = \{"dynamic static method added"}
> assert SomeClass.classDeclaredStatName == "in class definition static name"
> assert SomeClass.dynStaticMethod() == "dynamic static method added"
> //this forces conversion of metaClassImpl to expandoMetaClass
> SomeClass myc = new SomeClass()
> assert myc.name == "instance level name"
> assert myc.classDeclaredStatName == "in class definition static name"
> assert myc.dynProp == "dynamic property added"
> assert myc.dynMethod() == "dynamic method added as closure"
> assert myc.dynStaticMethod() == "dynamic static method added"
> def res
> res = myc.metaClass.properties //returns list of metaBeanProperty
> res = myc.metaClass.getMetaMethods() //works and returns list of metaMethods
> //This is the only method for static's in MOP - this works but you have to 
> know the name of the method in advance
> res = myc.metaClass.getStaticMetaMethod("dynStaticMethod", [] as ArrayList)
> //these functions are missing from MOP and would enable you to query for 
> static props/methods 
> res = myc.metaClass.getStaticMetaMethods()     //this method doesnt exist in 
> MOP api
> res = myc.metaClass.getStaticProperties()           //this method doesnt 
> exist in MOP api either
> {code}



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

Reply via email to