I have something like the plugin below where I have one outer namespace and within it there is a single 'concrete' instance (mother
) of an object plus another collection (children
).
family {
mother {
firstname = 'John'
lastname = 'Cleese'
}
children {
son {
firstName = 'John'
lastName = 'Cleese'
}
daughter {
firstName = 'Jane'
lastName = 'Cleese'
}
}
}
I am able to add the collection object and read the variables based on various examples I've seen but not sure how I add the concrete instance in addition.
How do I define it on the extension object?
Code which shows the issue - I would like to add mother
as a single instance withing the plugin.
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.*
class Person
{
final String name
String firstName
String lastName
Person(String name) { this.name = name }
}
class FamilyExtension {
final NamedDomainObjectContainer<Person> children
Person mother
Person father
FamilyExtension(children) {
this.children = children
}
def children(Closure closure) {
children.configure(closure)
}
}
class FamilyPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('sayHello', type: DefaultTask) << {
println(
"Hello ${project.family.children["son"].firstName} " +
"and hello ${project.family.children["daughter"].firstName} ")
}
def children = project.container(Person)
project.extensions.create("family", FamilyExtension, children)
}
}
apply plugin: FamilyPlugin
family {
// How do I add support for this?
// mother {
// firstname = 'John'
// lastname = 'Cleese'
// }
children {
son {
firstName = 'John'
lastName = 'Cleese'
}
daughter {
firstName = 'Jane'
lastName = 'Cleese'
}
}
}
Extra properties extensions allow new properties to be added to existing domain objects. They act like maps, allowing the storage of arbitrary key/value pairs. All ExtensionAware Gradle domain objects intrinsically have an extension named “ext” of this type.
buildscript: This block is used to configure the repositories and dependencies for Gradle. dependencies: This block in buildscript is used to configure dependencies that the Gradle needs to build during the project.
The subproject producer defines a task named buildInfo that generates a properties file containing build information e.g. the project version. You can then map the task provider to its output file and Gradle will automatically establish a task dependency.
The extension object is added to the plugin list with the name greeting. This object, then becomes available as a project property with the same name as the extension object. Gradle adds a configuration closure for each extension object, so you can group the settings together.
While creating a custom plugin, you need to write an implementation of plugin. Gradle instantiates the plugin and calls the plugin instance using Plugin.apply () method. The following example contains a greeting plugin, which adds a hello task to the project.
More on publishing projects to Gradle repository can be found in Gradle Plugin Portal Documentation. 5.5. Java Gradle Development Plugin When we're writing our plugins in Java, we can benefit from the Java Gradle Development Plugin.
In Gradle Property objects are a way to refer to a value before it’s actually set. This is useful with plugins and tasks since the property value may be referenced before its actual value has been configured in the build script. Use of abstract: the FileDiffExtension class itself and its methods are abstract.
Well, to add mother
closure to the family
you add the following code to the FamilyExtension
class
Person mother(Closure closure) {
mother = new Person()
project.configure(mother, closure)
return mother
}
If, at the same time you want to have children
extension inside family one you add the following code into the FamilyPlugin.apply
method
project.extensions.create("family", FamilyExtension, instantiator, project)
project.family.extensions.create("children", FamilyExtension.Children, project)
And then you add
void son(Closure closure) {
Person son = new Person()
project.configure(son, closure)
children.add(son)
}
to be able to add son
closure inside the children
one.
To see the whole project and explanation with more details please visit Github project https://github.com/andriipanasiuk/family-gradle-plugin
I was having a similar problem to yours, but I figured out how to create the "mother" on my case, but not the "children". The way that I accomplished this is with a nested extension object.
Here is how I did this (mine is in pure java, so you may need to make some changes to do it in Groovy - I'm very new to Groovy, so I'm not sure exactly what needs to be changed):
When you add your extension in the plugin, the class will automatically support the ExtensionAware interface, and thus can have extensions added to it. In your FamilyExtension constructor add a new extension, casting the class to ExtensionAware first:
public FamilyExtension(NamedDomainObjectContainer<Person> children) {
((ExtensionAware) this).getExtensions().create("mother",Person.class);
this.children = children;
}
This will only allow a single mother declared exactly as you have. Note, however, that it won't enforce only a single one, as you can add as many mothers as you want, but any later declarations will have the result of changing the value on that single instance, so there really is only one. You may also get a null value if the mother had not been declared, so will have to test for that (some demos say that this can happen, but in my own experiments it doesn't seem to).
To get your mother object, just cast your extension to ExtensionAware and retrieve the Person class off from that like you would get the family extension from the project
FamilyExtension fext = project.getExtensions().findByType(Person.class)
Person mother = (Person) ((ExtensionAware) fext).getExtensions().findByName("mother")
Edit: An alternative way would be just to define a function on your extension object which accepts a closure and have the closure delegate to a new mother object. Then you could use a Boolean flag to enforce the requirement of only one mother.
private boolean mother_defined = false;
private Person mother_value = null; // or Person mother = new Person()
public void mother(Closure<?> motherdef) {
if (mother_defined) {throw new Exception("Only one mother allowed");}
mother_value = new Person();
motherdef.setDelegate(mother);
motherdef.call();
mother_defined = true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With