I am in the process of implementing my first Gradle plugin where I need to define nested extension objects. The user manual does not cover this yet. Last year there were a few questions about this, but I canโt put together a solution from what I read.
Here is what I believe that I want the user to be able to:
yang { yangFilesRootDir "src/main/resources/yang" inspectDependencies true generators { generator { // line 25 generatorClassName "org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl" outputDir "build/gen1" } generator { generatorClassName "org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl" outputDir "build/gen2" } } }
My first random hit in this looks like this, and I'm sure it is not closed yet:
public void apply(Project project) { project.plugins.apply(JavaPlugin) YangExtension yang = project.extensions.create(YANG_EXT, YangExtension) project.yang.extensions.generators = project.container(CodeGeneratorsContainer) { println it }
Here are my extension classes:
class YangExtension { CodeGeneratorsContainer generators String yangFilesRootDir String[] excludeFiles boolean inspectDependencies String yangFilesConfiguration String generatorsConfiguration } public class CodeGeneratorsContainer { Collection<CodeGenerator> generators } class CodeGenerator { String generatorClassName File outputBaseDir Map additionalConfiguration }
When I started it right now, it fails with the following:
Caused by: java.lang.NullPointerException: Cannot get property 'name' on null object at org.gradle.api.internal.DynamicPropertyNamer.determineName(DynamicPropertyNamer.groovy:36) at org.gradle.api.internal.DefaultNamedDomainObjectCollection.add(DefaultNamedDomainObjectCollection.java:70) at org.gradle.api.internal.AbstractNamedDomainObjectContainer.create(AbstractNamedDomainObjectContainer.java:58) at org.gradle.api.internal.AbstractNamedDomainObjectContainer.create(AbstractNamedDomainObjectContainer.java:52) at org.gradle.api.internal.NamedDomainObjectContainerConfigureDelegate._configure(NamedDomainObjectContainerConfigureDelegate.java:39) at org.gradle.api.internal.ConfigureDelegate.invokeMethod(ConfigureDelegate.java:73) at build_2a353qtggi869feteaqu2qgc3$_run_closure1_closure3.doCall(....\workspace2\YangUsingProject\build.gradle:25)
And I highlighted line 25 in the build script, if that matters.
Update
After integrating the solution, this is a summary of the required configuration.
The structure of the sample in the file "build.gradle":
yang { yangFilesRootDir "src/main/resources/yang" //excludeFiles "target.yang" inspectDependencies true generator { generatorClassName = "org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl" outputDir = "build/gen1" } generator { generatorClassName = "org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl" outputDir = "build/gen2" } }
Method of using plugins:
public void apply(Project project) { project.plugins.apply(JavaPlugin) YangExtension yang = project.extensions.create(YANG_EXT, YangExtension, project) YangGenerateTask task = project.task(YANG_GENERATE_TASK, type: YangGenerateTask) project.afterEvaluate { task.init(project, yang) } }
Extension Class:
class YangExtension { private Project project Collection<CodeGenerator> generators String yangFilesRootDir String[] excludeFiles boolean inspectDependencies String yangFilesConfiguration String generatorsConfiguration YangExtension(Project project) { this.project = project } CodeGenerator generator(Closure closure) { def generator = project.configure(new CodeGenerator(), closure) generators.add(generator) return generator } }
And finally, CodeGenerator POGO:
class CodeGenerator { String generatorClassName String outputDir Map additionalConfiguration }