On 9 April 2014 at 5:23:35 am, Peter Niederwieser (pnied...@gmail.com) wrote:
All, 

as we are improving component metadata rules, we need a way for a rule to 
declare which metadata it is interested in. The current proposal is to do 
this via typed callback parameters. For example: 

dependencies { 
components { 
eachComponent { ComponentMetaDataDetails details, 
IvyModuleDescriptor descriptor -> ... } 
} 
} 

The rule above declares that it is interested in the generic metadata 
(`ComponentMetaDataDetails`) and Ivy specific metadata 
(`IvyModuleDescriptor`). Because it is interested in Ivy specific metadata, 
the rule will only fire for Ivy components. 

The set of potentially supported parameter types is open-ended. For example, 
future Gradle versions may support a `ArtifactoryProperties` parameter type. 

This raises some questions: 

* The above looks very much like a model rule. (`details` is the object to 
be mutated, `descriptor` is an input.) Should `eachComponent()` indeed 
accept a `ModelRule`, now or in the future? 
* If not, what should the Java API look like? 
* Do we want to generate the closure-based Groovy API from the Java API, now 
or in the future? 

For the time being, I've hand-coded the Groovy API, but obviously we also 
need a Java API. 

Thanks for any insights. 
Not sure it’s insightful, but here goes…

This is slightly different to the model rules we’ve implemented to date, but 
not different to the types of rules we’ve discussed or conceptualised.

Disclaimer: I don’t have a good understand of the component model, so I could 
be well off with what I’m about to say.

My understand is that conceptually we are transforming things (modules?) into 
components, and this hook allows you to augment how that should be done. So 
internally, there is a model rule that knows how to create components from 
module descriptors (roughly). We want to supply extra configuration to the 
created components, based on how they were created (i.e. what type of module 
descriptor they were created from). So, this is a model rule where the bindings 
are relative to the rule the created the thing to mutate. 

We currently don’t have any implementation for partially (potential other 
names: speculatively, relatively) bound rules. Currently, the rule itself 
dictates how it is bound to the model. In this case, The same rule can be 
reused and be bound to different elements each time because the bindings are 
not absolute. So, this is some context specific sugar that would somehow create 
many absolutely bound rules (in some form) from the partially bound rule.

In terms of API, the complication here is that there are constraints on the 
rule. It can only mutate a ComponentMetaDataDetails. Arbitrary targets don’t 
make sense. I can’t see an easy way to express “first argument must be <T>, but 
the rest are any <? extends X>”. Java’s type system isn’t up for this. We are 
going to have this problem generally for the model rules of course.

One possibility for a general pattern would be something like…

interface Components {

  void eachComponent(MutationRules<ComponentMetaDataDetails> rules) {}

}

abstract class MutationRules<T> {
  public final T getTarget() {

    // retrieve the target from some thread scoped global that we manage

  }

}

components.eachComponent(new MutationRules<ComponentMetaDataDetails>>() {

  // arbitrary methods in here that act as rules, with arbitrary signatures

})

We could then as a common pattern, transform this kind of method to…

void eachComponent(@DelegatesTo(ComponentMetaDataDetails) Closure<?> closure)

So the closure delegate is the target, and all of the closure params are inputs.



I’ll keep thinking on it.











Reply via email to