I am new to Gradle and have just written a Plugin. I also have read about the Model concept, which I really like. I wanted to access Model information from a Plugin.
I tried to get it from Project since my plugin takes Project as input (Plugin). The closest model related property is Model Schema Store. However this looks to be from ‘internal’ package.
Is it possible to access Model from a Plugin? How I can do so? Apologies if I am missing the obvious.
As far as I’ve seen, you don’t really need to access the model from a plugin directly, you just provide rules that take model elements as inputs, and it’s all automagic from there.
Following up on what Andreas said, the new software model is a parallel configuration mechanism to the old plugin approach. They’re not mutually exclusive, but there are only limited ways to link between them.
To use the new model, create one or more classes that implement RuleSource. I tried to provide an introduction to the new structure in a presentation. If you have a spare hour, it may help.
If you want to have your RuleSource processed by Gradle automatically when a user applies your plugin, then you can simply make that RuleSource a static inner class of the plugin, as demonstrated here.
Maybe I wasn’t clear enough with what I mean by ‘accessing the model’.
I am working on a PlantUml plugin, which can generate diagrams like Component or Use Case. I would like to be able to read the model (builtin entities like Components but also my own entities like UseCase) and then to generate a diagram.
In essence, I need same information as you can get with ‘gradle model’ command, but programmatically with my own Plugin.
I couldn’t understand how I can do that via RuleSets…
@amilenovic there is no public API available to inspect the entire model graph. The model task uses the internal class org.gradle.model.internal.registry.ModelRegistry to cycle through the nodes of the model. Classes like ModelRegistry are under active development and are intentionally not made public. It is not recommended for external plugins or builds to rely on and use such classes so use at your own peril!
The return type and significance of the rule name both depend on the type of rule, but for now I want to focus on <input>, .... These inputs represent other elements of the model, provided by your own plugin, core Gradle, or some other plugin. Gradle automatically injects the appropriate object of the required type into your rule method. You can then extract the information you need and do something with it.
For example, if you want to create some tasks based on the configured use case, you can do this:
@Mutate
void createUseCaseTasks(ModelMap<Task> tasks, UseCase useCase) {
tasks.create("useCaseTask") {
// Configure the task using information from `useCase`
...
}
}
What if you have more than one UseCase in your model? In that case, you either need to use a collection of them (via ModelMap for example) or specify a specific one based on its model path (via the @Path annotation).
If not much of this is making sense, then you’ll need to learn more about the new software model. I used the videos of the relevant workshop from the Gradle Summit. That’s a link to part 1. Just change the 1 for a 2 in the URL to get the second part, although I feel all the important stuff is in the first one.
Got it, thanks @Adrian_Kelly. I hope you will eventually make such API public - I see it as an excellent base for ecosystem of tooling on top of Gradle.
creates a tasks by first evaluating “UseCase”. is there a way to achieve this the other way around? Like
@TaskAction
public void doSomething(UseCase useCase)
Meaning that I would like to evaluate the model if a given task is executed (because the task needs this part of the model, but not other parts of the model that are potentially expensive to evaluate)? The given example results in a gradle error.