GDSL Awesomeness – Understanding Context And Contributors in Detail
GDSL Scripts are based on two main concepts: contexts and contributors. Hence we will discuss about these in detail here.
In GroovyDSL context is an entity which is supposed to give an answer to the question “Where?” this behavior will be available. Contexts are first-order citizens in GroovyDSL, so they may be stored in local script variables and passed as parameters.
Context can be defined as:
[java]
def ctx = context(ctype: ,
filetypes: [*],
scope: )
[/java]
Context is a predefined method in the GDSL Scripts.
When no argument is passed in context it means “everywhere”.
Below we describe possible values of optional parameters:
- Reference class type “ctype”: A string, representing a fully qualified name of a class type to be augmented with the new behavior. In case this argument is missing then java.lang.Object class type is taken as a type to be augmented.
- Supported file types “filetypes”* A possible empty list of comma-separated file extensions passed as strings or GString instances , this will restrict the behavior to the files with the passed extensions.
- Script type “scriptType”: A string denoting the script type ID, e.g. ‘gant’, ‘gradle’, ‘default’. Differs from “fileTypes” in that it doesn’t depend on the extension. For example, the Gant scripts in Grails usually have groovy extension.
- Path pattern “pathRegexp”: A regexp that should match the path to the Groovy file where your script contributes to. The path always uses forward / slashes.
- Context scope “scope”: A scope of a current context. If no scope passed to a context, it is assumed to capture all possible places, where other conditions are applicable. It may be of three different kinds:
- scriptScope(name : ) The scope of a behavior defined in this context is available in a script body as well as in its inner closures, for instance, ones which are passed as method arguments. scriptScope() method takes one optional parameter which should be a string, GString or a regular expression. In a presence of this argument appropriate script names will be matched against it. By default the value of this parameter is an all-matching regular expression.
- classScope(name : ) Restricts the scope of an actual behavior to the class with some particular properties, such as (rules for class naming filter are same as for ScriptScope).
- closureScope(isArg: Boolean) This scope describes Groovy’s closure blocks. There is an important case of closure, passed as a parameter to a method, replacing its delegate, which allows to invoke callee’s unqualified methods in a body of closure. The typical example of such a behavior is identity() method of groovy.lang.GroovyObject class. This case may be captured by passing an optional named parameter isArg to the closure.
Contributors
Contributors are entities which consume contexts as initialization parameters and answer to the question “What?”.
In contributors we define the properties or methods to inject.
New contributor may be defined by an invocation of a method contributor(), taking two parameters:
- A list of contexts to be used to contribute a new behavior
- Zero-argument closure, adding new behavior to the reference expression “in the focus” of a context
The code fragment below shows the definition of a contributor, taking a list of three contexts, defined earlier, namely ctx1 and ctx2 and one closure, which adds unconditionally the method foo with a parameter of type java.lang.String and return type int to the target expression of a context.
[java]
contributor [ctx1, ctx2], {
method name: "foo", params: [bar: "java.lang.String"], type: "int"
}
[/java]
Read Further in the “GDSL AWESOMENESS” Series
- GDSL Awesomeness – Introduction to GDSL in IntelliJ Idea
- GDSL Awesomeness – Understanding Context And Contributors in Detail
- GDSL Awesomeness – Defining dynamic property in a class
- GDSL Awesomeness – Defining dynamic method in a class
- GDSL Awesomeness – Adding Hinting for missingMethod implementation
- GDSL Awesomeness – Setting a global context
- GDSL Awesomeness – Delegating Closure Calls
- GDSL Awesomeness – Defining methods in a closure passed to method of particular name
- GDSL Awesomeness – Defining Properties in a closure passed to method of particular name
- GDSL Awesomeness – Contributing to classes which match a path/name pattern
- GDSL Awesomeness – contributing methods with current class return types or parameters
- GDSL Awesomeness – AutoComplete Script for grails-Mail-Plugin “sendMail” closure
- GDSL Awesomeness – Getting Code of a method or Field in GDSL Script
- GDSL Awesomeness – Advanced Example showing domain properties implementation
Hope It Helped.
Kushal Likhi