Have a question related to chapter from custom_plugins; “52.6. Maintaining multiple domain objects”. In the example here there is Book object created and used for the project.container(Book) where-in it is available for flexible definition.
Is it possible to add another flexible object; say page/chapter inside the another (as in example; Book)
As far as I know it is not possible with public Gradle API. Even if it was, it would be using a named extension on the container element, rather than having the container element being a container itself:
books {
book1 {
chapters {
chapter1
}
}
}
I also needed such support but since it was not available, I ended up using the internal Gradle ‘Instantiator’ class to implement it. It can mix in ExtensionAware in the generated container element instance:
import org.gradle.internal.reflect.Instantiator
project.extensions.books = project.container(Book) { String name ->
Book book = gradle.services.get(Instantiator).newInstance(Book, name)
assert book instanceof ExtensionAware
return book
}
After mixing ExtensionAware in the generated Book instance, you can create a nested container extension using ExtensionAware.add method:
project.extensions.books = project.container(Book) { String name ->
Book book = gradle.services.get(Instantiator).newInstance(Book, name)
//add a nested container extension
book.extensions.add('chapters', project.container(Chapter))
return book
}
class Chapter {
final String name
public Chapter(String name) {
this.name = name
}
}
However, although creating a nested container extension will work, it will not behave correctly if you configure it with a closure. It seems it always delegates to the parent container, so if you use the above code snippet, you will actually get 2 Book instances named ‘book1’ and ‘chapter1’ respectively, rather than a ‘book1’ Book instance containing a ‘chapter1’ Chapter.