Nested model methods

I’m trying to do something similar to what has been posted in the past and I believe I am either hitting a regression bug, something I’m doing wrong, or something that has been deprecated/removed. I am using Gradle 2.8.

Starting with some working code:

@Managed
interface Inner {
    void setSomething( String something )
    String getSomething()
}

@Managed
interface Outer {
    Inner getInner()
}

class NestedRules extends RuleSource {
    @Model void outer( Outer out ) {}
    @Mutate void createTask( ModelMap<Task> tasks, Outer out ) {
        tasks.create( 'printInner' ) {
            doLast {
                println out.inner.something
            }
        }
    }
}

apply plugin: NestedRules

model {
    outer {
        inner.something = 'Hi'
    }
}

All is well with the printInner task:

$ ./gradlew printInner
:printInner
Hi

Now I want to enable configuration of inner using the following syntax:

model {
    outer {
        inner {
            something = 'Hello'
        }
    }
}

So based on the previously mentioned post I tried adding the following to the RuleSource:

@Model void inner( Inner inner ) {}

which fails with:

A problem occurred configuring root project 'gradle-model-test'.
> Exception thrown while executing model rule: model.outer
   > Could not find method inner() for arguments [build_11skrf6fkeskg40vkwyzi3uh7$_run_closure2$_closure3$_closure4@e56dbc1] on root project 'gradle-model-test'.

Based on my understanding it makes sense that I now have a working root inner() method, but I’m not sure how to get an outer.inner() method working instead. i.e. this now configures successfully but isn’t what I want:

model {
    outer {
        inner.something = 'Hi'
    }
    inner {
        something = 'Hello'
    }
}

Thanks, Chris

+1

I´m puzzling my head over the exact same question. After one day of research I am as far as Chris and wonder wether it is possible to edit nested model element via the dsl and the above syntax at the moment.

@Jan, this has now been improved in Gradle 2.10 and it possible to configure properties of managed types.

See Configure the properties of a @Managed type section of the release notes.

When a setter is provided, this method no longer seems to work, as noted here. Is there any way to use the new syntax provided in Gradle 2.10, while retaining a setter?

What I’d like to be able to do is this:

model {
    outer {
        // Set properties on inner, where inner is provided by a default object, as it does
        // when the getter is removed.
        inner {
            something = 'Hello'
        }
    }
}
model {
    outer {
        // Replace inner entirely with another instance
        // elsewhere, sharing the reference.
        inner = $.elsewhere.in.the.model
    }
}