I have this auto generated lines of codes:
EPRole validator: { EPRole r, EPUserEPRole ur ->
if (ur.EPUser == null) return
boolean existing = false
EPUserEPRole.withNewSession {
existing = EPUserEPRole.exists(ur.EPUser.id, r.id)
}
if (existing) {
return 'userRole.exists'
}
}
When I try to compile the code I get 82: unexpected token: validator # line 82, column 10.
I am new in groovy so any help is appreciated.
You should add your properties with the proper type and name to the class. First letter uppercase is for classes (or types in general). So there should be in your EPUserEPRole a property like this:
EPRole epRole
Then add the validator for epRole. Pay attention to the case.
Above code would confuse the groovy parser into defining a property validator of type EPRole followed by a :, hence the error (or else it would try to call the method EPRole with the map, depending on context).
Related
The code in popup.setOnMenuItemClickListener is lambda expression, the function of the code is to show a popup menu.
It's hard to understand lambda expression sometimes.
Is there a simple way to convert a lambda into a full expression ? Is there some utilities to do that?
Code
private fun showPopup(v: View, mContext: Context) {
val popup = PopupMenu(mContext, v)
popup.inflate(R.menu.menu_popup_more)
popup.setOnMenuItemClickListener {
when (it.itemId) {
R.id.MenuMoreAbout->{
requireActivity().openActivity<UIAbout>()
}
}
true // Why do I need add 'true'
}
popup.show()
}
Is there a simple way to convert a lambda into a full expression ?
Yes there is! First position the cursor on the first curly brace
Position your cursor at this character
|
v
popup.setOnMenuItemClickListener {
when (it.itemId) {
R.id.MenuMoreAbout->{
requireActivity().openActivity<UIAbout>()
}
}
true // Why do I need add 'true'
}
then type Alt+Enter (Option+Enter for Mac) to bring up the Quick Fix menu. Select Convert to anonymous function. That will turn the code into the following:
popup.setOnMenuItemClickListener(fun(it: MenuItem): Boolean {
when (it.itemId) {
R.id.MenuMoreAbout -> {
requireActivity().openActivity<UIAbout>()
}
}
return true
})
which is clearer for someone that is new to Kotlin syntax.
As can be seen, your true expression was the return value of the lambda. In Kotlin, the return value of a lambda is the value of the last expression in the lambda. If you prefer, you can make this explicit by replacing
true // Why do I need add 'true'
with
return#setOnMenuItemClickListener true
in your original code. See official docs for Return at Labels for more information.
The reason a Boolean has to be returned is because the lambda is for the following Java interface which is the type of the argument to setOnMenuItemClickListener(OnMenuItemClickListener)
public interface OnMenuItemClickListener {
boolean onMenuItemClick(MenuItem item);
}
As you can see, onMenuItemClick(MenuItem) returns a boolean (which is converted to Boolean in Kotlin). So the lambda must also return a Boolean.
I have a rule that looks like this:
INTEGER : [0-9]+;
myFields : uno=INTEGER COMMA dos=INTEGER
Right now to access uno I need to code:
Integer i = Integer.parseInt(myFields.uno.getText())
It would be much cleaner if I could tell antler to do that conversion for me; then I would just need to code:
Integer i = myFields.uno
What are my options?
You could write the code as action, but it would still be explicit conversion (eventually). The parser (like every parser) parses the text and then it's up to "parsing events" (achieved by listener or visitor or actions in ANTLR4) to create meaningful structures/objects.
Of course you could extend some of the generated or built-in classes and then get the type directly, but as mentioned before, at some point you'll always need to convert text to some type needed.
A standard way of handling custom operations on tokens is to embed them in a custom token class:
public class MyToken extends CommonToken {
....
public Integer getInt() {
return Integer.parseInt(getText()); // TODO: error handling
}
}
Also create
public class MyTokenFactory extends TokenFactory { .... }
to source the custom tokens. Add the factory to the lexer using Lexer#setTokenFactory().
Within the custom TokenFactory, override the method
Symbol create(int type, String text); // (typically override both factory methods)
to construct and return a new MyToken.
Given that the signature includes the target token type type, custom type-specific token subclasses could be returned, each with their own custom methods.
Couple of issues with this, though. First, in practice, it is not typically needed: the assignment var is statically typed, so as in the the OP example,
options { TokenLabelType = "MyToken"; }
Integer i = myFields.uno.getInt(); // no cast required
If Integer is desired & expected, use getInt(). If Boolean ....
Second, ANTLR options allows setting a TokenLabelType to preclude the requirement to manually cast custom tokens. Use of only one token label type is supported. So, to use multiple token types, manual casting is required.
In Groovy, if I have:
def say(msg = 'Hello', name = 'world') {
"$msg $name!"
}
And then call:
say() // Hello world!
say("hi") // Hi world!
say(null) // null world!
Why is the last one getting interpreted literally as null and not applying the default value? Doesn't this defeat the purpose of default method argument values? I do get that passing null is different from not passing anything w/r/t argument length.
My problem here is that if I now have a method that takes a collection as an argument:
def items(Set<String> items = []) {
new HashSet<>(items)
}
This will throw a NullPointerException if I call items(null) but work fine if I just say items(). In order for this to work right, I have to change the line to be new HashSet<>(items ?: []) which, again, seems to defeat the entire purpose of having default method argument values.
What am I missing here?
In Groovy, default parameters generates overloaded methods. Thus, this:
def items(Set<String> items = []) {
new HashSet<>(items)
}
Will generate these two methods (I used javap to get these values):
public java.lang.Object items(java.util.Set<java.lang.String>);
public java.lang.Object items();
So when you call items(null) you are, in fact, passing some value, and items(Set) method will be used.
You can also refer to this question about default parameters.
I am attempting to create a ternary expression and I am getting the following error
"Type of conditional expression cannot be determined because there is no implicit conversion between LiveSubscription and DisconnectedSubscription"
The same logic works in an if statement, but I wanted to understand why it won't work in a ternary expression -
Here is the gist of what I am trying to do:
public interface IClientSubscription
{
bool TryDisconnect();
}
public class LiveSubscription : IClientSubscription
{
public bool TryDisconnect()
{
return true;
}
}
public class DisconnectedSubscription : IClientSubscription
{
public bool TryDisconnect()
{
return true;
}
}
public class ConnectionManager
{
public readonly IClientSubscription Subscription;
public ConnectionManager(bool IsLive)
{
// This throws the exception
Subscription = (IsLive)
? new LiveSubscription()
: new DisconnectedSubscription();
// This works
if (IsLive)
{
Subscription = new LiveSubscription();
}
else
{
Subscription = new DisconnectedSubscription();
}
}
}
I could always switch it to an if/else but I wanted to understand what is going wrong first!
You need to cast at least one of the operands to IClientSubscription:
Subscription = (IsLive)
? (IClientSubscription)new LiveSubscription()
: new DisconnectedSubscription();
The reason is that the ternary expression is of a certain type which is determined by the operands. Basically, it tries to cast the second operand to the type of the first or vice versa. Both fail here, because LiveSubscription isn't an DisconnectedSubscription and vice versa.
The compiler doesn't check whether both share a common base type.
Trying to answer your question in the comment:
No, ternary expressions are not some sort of object, but a ternary expression is the right hand part of an assignment. Each right hand part expression of an assignment has a certain type, otherwise it would be impossible to assign this expression to the variable on the left hand side.
Examples:
var x = Guid.NewGuid()
The right hand side expression (Guid.NewGuid()) is of type Guid, because the method NewGuid() returns a Guid.
var x = y.SomeMethod()
The right hand side expression is of the type of the return type of SomeMethod().
var x = IsLive ? "a" : 1
This is obviously invalid, isn't it? What type should x be? A string or an int?
This would lead to the exact same error message that you had with your code.
Your example a bit changed:
var subscription = (IsLive) ? new LiveSubscription()
: new DisconnectedSubscription();
Note the var before subscription, we now initialize a new variable, not an existing. I think even here, it is obvious what the problem is: What type should subscription be? LiveSubscription or DisconnectedSubscription? It can be neither, because depending on IsLive it needs to be either the one or the other.
About the comparison with if:
In your code where you assign a new LiveSubscription instance or a new DisconnectedSubscription instance to Subscription an implicit cast to IClientSubscription is occurring, because the compiler knows that Subscription is of type IClientSubscription and both LiveSubscription and DisconnectedSubscription can implicitly be converted to that interface.
The assignment with the ternary expression is a bit different, because the compiler first tries to evaluate the ternary expression and only afterwards it tries to assign it to Subscription. This means that the compiler doesn't know that the result of the ternary expression needs to be of type IClientSubscription.
I am currently using CSS to change everything I write to upperCase when I create an entry, but that is not enough. When I save things, the text shown in the text fields is upper case, but the real value that Grails stores stays in lower case.
I am assuming I'd need to change something in the controller or anything.
Maybe transforming the $fieldValue CSS could work??
Any ideas would help!
Thnks!
You could just write setters for your domain object?
class Domain {
String aField
void setAField( String s ){
aField = s?.toUpperCase()
}
}
I think you are asking how to change values on your domain objects to uppercase. If this is not the case please clarify the question.
You have a bunch of options. I would recommend
1) In a service method, before you save, using String.toUpperCase() to modify the appropriate values on the domain object.
or
2) You can use the underlying Hibernate interceptors by defining a beforeInsert method on your domain object, and doing the toUpperCase there. (see 5.5.1 of the grails documentation)
or
3) You could do this client side. However, if it is a "business requirement" that the values are stored as upper, then I recommend doing the translation server side. It is easier to wrap tests around that code....
Using annotations is cleanest approach
import org.grails.databinding.BindingFormat
class Person {
#BindingFormat('UPPERCASE')
String someUpperCaseString
#BindingFormat('LOWERCASE')
String someLowerCaseString
}
Here is link for it: Grails doc for data binding
You can use Groovy metaprogramming to change the setter for all domain class String-typed properties without actually writing a custom setter for each property.
To do this, add something like the following to the init closure of Bootstrap.groovy
def init = { servletContext ->
for (dc in grailsApplication.domainClasses) {
dc.class.metaClass.setProperty = { String name, value ->
def metaProperty = delegate.class.metaClass.getMetaProperty(name)
if (metaProperty) {
// change the property value to uppercase if it's a String property
if (value && metaProperty.type == String) {
value = value.toUpperCase()
}
metaProperty.setProperty(delegate, value)
} else {
throw new MissingPropertyException(name, delegate.class)
}
}
}
}