Extension containing a NamedDomainObjectContainer

I am working on a plugin that defines an Extension where I would like that Extension to hold a NamedDomainObjectContainer. It is a JAXB/XJC plugin. The top-level Extension holds information for processing all XSDs. And for each XSD to be processed I’d like to have a NamedDomainObjectContainer holding descriptors of that config. I visualize the DSL as:

jaxb {
  outputDir = ...

  schemas {
    cfg {
      xsd = file( ... )
      ...
    }
    hbm {
      xsd = file(...)
      xjcBinding = file(...)
      ..
    }
  }
}

cfg and hbm are meant to represent the named domain objects. The way the plugin is structured is that the plugin registers the extension:

JaxbExtension extension = project.getExtensions().create( "jaxb", JaxbExtension, project )

and JaxbExtension holds the NamedDomainObjectContainer:

class JaxbExtension {
  ..
  final NamedDomainObjectContainer<SchemaDescriptor> schemas;
}

For the life of me though I cannot figure out how to wire this all up. I have tried the DSL snippet above, but end up with:
> Could not find method schemas() for arguments [build_8dyounopx7k45aqwxkd22bp9p$_run_closure4_closure6@481ef3e] on project ‘:java6-module’.

I also tried without the schemas {} grouping:
> Could not find method cfg() for arguments [build_8dyounopx7k45aqwxkd22bp9p$_run_closure4_closure6@7b42a00f] on project ‘:java6-module’.

Is what I am trying possible? Any pointers on implementing it?

1 Like

You have to provide a little bit more than just a instance variable definition on your extension object. First you have to create a container. You can do this by calling Project.container(). Add the following to the constructor of JaxbExtension.

this.schemas = project.container(SchemaDescriptor)

You’ll also have to add a method that takes a closure as an argument which configures your container. Add the following method to your extension object.

def schemas(Closure config) {
    this.schemas.configure(config)
}

Last, you’ll want to ensure that the container type, in this case SchemaDefinition, has a property called ‘name’ and a public constructor which takes the ‘name’ as a String argument.

2 Likes

Thanks Mark. I actually do have the call to Project#container, I just did not include it in the snippet above. Here is a more complete picture of what I have there:

class JaxbExtension {
  ...
  final NamedDomainObjectContainer<SchemaDescriptor> schemas;

  public JaxbExtension(Project project) {
    this.project = project;

    ...

    // Create a dynamic container for SchemaDescriptor definitions by the user
    schemas = project.container( SchemaDescriptor, new SchemaDescriptorFactory( project ) )
}
}

and:

class SchemaDescriptorFactory implements NamedDomainObjectFactory<SchemaDescriptor> {
  final Project project;

  SchemaDescriptorFactory(Project project) {
    this.project = project
  }

  @Override
  SchemaDescriptor create(String name) {
    return new SchemaDescriptor( project, name )
  }
}

Sorry, I should have posted that before.

I guess what I am missing now is the configure method on JaxbExtension. I will try that now. Thanks again!

Adding the schemas(Closure) method to JaxbExtension dids the trick! Thanks again Mark!