Is it possible to have complex/nested multiple domain objects?


(Abhijeet Shinde) #1

Hi,

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)

So something like:

books {

quickStart {

sourceFile = file(‘src/docs/quick-start’)

page1{

chapter = “abc”

}

page2{

chapter = “efg”

}

}

userGuide {

}

developerGuide {

} }

Thanks & Regards


(detelinyordanov) #2

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.