Is there a way to parametrize mixin in Groovy? - groovy

Can I somehow mixin a class with parameterized constructor?
Something like this:
class RenderedWithTemplates {
def templates = []
RenderedWithTemplates(templates) { ... }
...
}
#Mixin(RenderedWithTemplates(show: "showAddress.gsp", add: "addAddress.gsp")
class Address { ... }

I found the mixin proposal from 2007 [0], but the GroovyDefaultMethods#mixin [1] method has no support for parameterized mixins and neither has #Mixin.
As far as I can tell from the code example above, you need to find a way to mixin GSP view information that is tied to your (domain) classes. An alternative (and slightly groovier ;)) approach for this case would be to implement RenderedWithTemplates as annotation with a single closure parameter holding the GSP view information:
import java.lang.annotation.*
#Retention(RetentionPolicy.RUNTIME)
#interface RenderedWithTemplates {
Class value()
}
#RenderedWithTemplates({ [show: "showAddress.gsp", add: "addAddress.gsp"] })
class Address {}
// shows how to read the map with all the GSP infos
def templateInfo = Address.getAnnotation(RenderedWithTemplates)
def gspMap = templateInfo.value().newInstance(this, this).call()
[0] http://docs.codehaus.org/display/GroovyJSR/Mixins
[1] http://groovy.codehaus.org/api/org/codehaus/groovy/runtime/DefaultGroovyMethods.html

Related

Loopback 4: How to edit metadata set by `#property` decorator on `Entity` props?

I use a third party Entity class with custom props. I extend it and need to add additional meta to already existing props defined inside the class I extend.
Here a code example. It doesn't work and is written only to explain better what I would like to accomplish:
export abstract class MyEntity extends ThirdPartyEntity {
#property({
// This is additional meta I want to add.
myMetaProp: 'some value'
})
// This prop is already defined and decorated with `#property` in the `ThirdPartyEntity`.
thirdPartyProp: string;
}
As mentioned above, this doesn't work. It produces this error - #property cannot be applied more than once on.
You can't add/remove or override alltogether the meta defined by the #property decorator.
I resolved to use this workaround MyEntity.definition.properties.thirdPartyProp.myMetaProp = 'some value'.
The question is: is there any better and declarative way of editing the props meta? I've tried with MetadataInspector.defineMetadata but accomplished nothing.

Can Groovy Trait Return Implementing Type Suitable for Method Chaining

Is it possible to incorporate trait methods along with methods on the implementing class using method chaining? This requires that the trait return the specific type of the implementing class, and the "this" variable is not that type by default.
Something like:
def withFilter(String filter){
this.filter = filter
return (super.getClass())this
}
According to the top answer on the post below, it looks to be pretty easy to achieve with Scala Traits, but I don't understand the syntax exactly. It looks like it uses a closure which defines it's return type, but is the same possible in Groovy?
Best practice to implement Scala trait which supports method chaining
You can use generics approach.
Here is an example
trait MyTrait<T extends MyTrait<T>> {
def filter
T withFilter(String filter) {
this.filter = filter
return (T) this
}
}
class MyClz implements MyTrait<MyClz> {
def clzMethod() {}
}
def clz = new MyClz()
.withFilter("hello")
.withFilter("another")
.clzMethod()

In which sequence does method call work in groovy?

I am using groovy 2.3.8
I am trying to figure out how method calls work in groovy. Specifically if we have a Java class hierarchy each having a metaClass like below
class A {
}
A.metaClass.hello = {
"hello superclass"
}
class B extends A {
}
B.metaClass.hello = {
"hello subclass"
}
If I use new B().hello() I get hello subclass. If I remove meta class of B then I get hello superclass.
Based on changing the above example I think groovy goes in the below sequence to find which method to call
method-in-subclass's-metaclass ?: subclass-metho ?: method-in-superclass's metaclass ?: method-in-superclass
So how does groovy lookup which method to call?
Well, the hierarchy is the expected object oriented programming method overloading, which is what you witnessed. What differs is the dispatching. Instead of starting with a method lookup in instance's class, it begins with the MOP (meta object protocol).
In layman's terms, because the MOP is programmable, so is the way methods are invoked :)
How it works
The following diagram from Groovy's documentation shows how methods are looked up.
What's not clear in the diagram is that there's an instance metaclass as well, and it comes before the class's metaclass.
Something that may help is looking at an object's or class's .metaClass.methods Methods added through inheritance, traits, metaclass, etc are listed in a flat list. The inheritance hierarchy is flattened. .metaClass.metaMethods on the other hand seems to contain methods added via the GDK. From the list I could not tell method precedence :(
Based on observation, the rule seems to be this: the last MetaClass standing wins.
class A { }
class B extends A { }
A.metaClass.hello = {
"hello superclass"
}
B.metaClass.hello = {
"hello subclass"
}
def b = new B()
assert b.hello() == "hello subclass"
b.metaClass = A.metaClass
assert b.hello() == "hello superclass"

How to check you have landed on one of several pages in Geb

I'm new to Groovy and testing a website with reasonably complex workflows using Geb/Cucumber.
I have a set of product pages represented by page classes Prod1Page, Prod2Page and Prod3Page. They share certain characteristics that can be tested by the same code.
I want to write a ProductPage page class along the lines of:
class ProductPage extends Page {
...
static at = {...}
...
}
so that
Given(~/.../) {
...
at ProductPage
...
}
would pass if any of the following were true:
at Prod1Page
at Prod2Page
at Prod3Page
In case it's not clear my goal is to avoid duplicating the details of Prod[1-3]Page classes somewhere else.
Thanks for any insights,
Nick
In the ProductPage's at checker just assert that the common HTML elements between all Prod#Pages are available. For example, if all ProdPages have a <div id="productContainer"> element then you can put the following in your ProductPage class:
class ProductPage extends Page{
static at = { $("#productContainer").displayed }
...
}
Now in your test you can call at ProductPage and it will assert true if that common element is currently available on the WebDriver's DOM; and you will know that you are on one of the ProdPages.

How to Parse multiple classes from groovy file

Is there a way to parse all all the classes in a groovy script?
To Parse ONE class right now:
java.lang.Class clazz = groovyClassLoader.parseClass(new File("MainApp.groovy"))
MainApp.groovy:
class MainApp {
def doIt() {}
}
class OtherMainApp {
def doTheRest() {}
}
This will return only MainApp.
I would like something like this:
java.lang.Class[] clazz = groovyClassLoader.parseClass(new File("MainApp.groovy"))
where clazz contains will contain both MainApp class and OtherMainApp class
Basically I want to be able to extract all the declared classes in a script.
Because of the nature of the app that I'm building groovyc command won't help
Thanks,
Federico
No can do:
https://issues.apache.org/jira/browse/GROOVY-3793
You could do it yourself though: you could parse the class yourself (just count the {} pairs), dump it out to a new file, and away you go. Ugly? yes. Painful? Very. Possible? Maybe. Better solution? Not until Groovy fixes the bug.
It's been 12 years since this question was asked and answered, but it arrived at the top of my Google results when I was trying to figure out how to do the same thing.
This ended up working for me:
def loader = new GroovyClassLoader()
loader.parseClass(new File("Company.groovy"))
Class Location = loader.loadClass("tk.vallerance.spacecompanies.models.Location")
Class Event = loader.loadClass("tk.vallerance.spacecompanies.models.Event")
Class Company = loader.loadClass("tk.vallerance.spacecompanies.models.Company")
println Location
println Event
println Company

Resources