What is the proper way of calling a method in Groovy - groovy

In fact, my issue is a lot broader than I could explain in the title. I'm having a problem with understanding a code in Groovy that's supposed to be fairly easy to understand. Please have a look at the following piece of code.
// event handlers are passed the event itself
1:def contactHandler(evt) {
2: log.debug "$evt.value"
3:
4: // The contactSensor capability can be either "open" or "closed"
5: // If it's "open", turn on the light!
6: // If it's "closed" turn the light off.
7: if (evt.value == "open") {
8: switch1.on();
9: } else if (evt.value == "closed") {
10: switch1.off();
11: }
12:}
I can understand everything starting that falls after the line 2, but If lines 8 or 10 are the proper way of calling a method, then what the heck is going on in the line 2? I can understand that log.debug means "debug" function of the class called "log".(Or something similar) But what is that blank space after it? And more than that, why does it say "$evt.value", when it can simply say "evt.value" in lines 8 and 10? And why isn't there a semicolon at the end of the line. I know, they're optional, but as far as I can see there's a convention as to when to use them and when to not. And lastly, I have a stranger line of code which totally insane (to me of course):
11: section ("When the door opens/closes...") {
12: input "contact1", "capability.contactSensor",
13: title: "Where?"
14: }
How should I understand the line starting from 12?
I've taken a look at http://groovy.codehaus.org/ but couldn't decide what to look for in order to find an explanation.

Ok, so from the beginning:
In groovy you can omit parentheses () when calling a method with arguments. So
log.debug 'lol'
is exactly the same as:
log.debug('lol')
Since on() and off() don't have any arguments, there's a need to use parens - or they might be mistaken with on and off fields. Blank separates method from arguments.
evt.value vs "$evt.value" - it's not the same. First is just a literal string, the second one is GString. First will print evt.value while the second one will evaluate the value of value variable for evt object. It might open or closed as further code shows.
Semicolon is optional, that's all I can say. No idea why semicolons are there. Sometimes there's a need to use semicolon - in oneliners e.g.
items.collect { print it; it*it }
Starting from line no.12 it's also a method call. It's equal to:
input("contact1", "capability.contactSensor", title: "Where?")
It's passing a map as the first parameter, and then two strings as the second and third parameters.
Further reading:
Methods - look also for named parameters.
Optionality
All docs

Related

How to skip a Parameter with Default Values in Groovy?

My Groovy method has 3 parameters and the last 2 have default values. I want to skip the second parameter, and only provide values for the first and the third like so..
def askForADate(girlsName, msg = 'Will you go out with me?', beg = 'pretty please!!') {
println "$girlsName, $msg $beg!"
}
askForADate('Jennifer',,'Because I love you!')
Right now this prints out...
Jennifer, Because I love you! pretty please!!!
So it looks like it is plugging the value I am passing in for the third parameter into the second.
How to fix that?
As doelleri said, you'll need to write two version of thie method.
Unless you'll use some groovy goodness with named arguments!
def askForADate(Map op, girlsName) {
println "$girlsName, ${op.get('msg', 'Will you go out with me?')} ${op.get('beg', 'pretty please!!')}!"
}
askForADate(beg: 'Because I love you!', 'Jennifer')
Prints out: Jennifer, Will you go out with me? Because I love you!!
See http://mrhaki.blogspot.com/2015/09/groovy-goodness-turn-method-parameters.html for more details
This solution has the clear disadvantage of reordering the arguments as now the girls name is last in line.

Switching on String Value Yields Unexpected Results in Groovy

I am working in a groovy/grails set up and am having some trouble trying to execute a switch statement on a String value.
Basically, I am looping through the attribute names in a webservice response to see if they match pre-defined mappings that are configured on a per user basis. If they have established a mapping on that field, I pull the value out of the response and use it elsewhere.
The code looks something like this:
switch(attributeName)
{
case {attributeName} :
log.info("Currently switching on value... ${attributeName}")
case user.getFirstNameMapping():
model.user.userInfo.firstName = attributeValue
break
case user.getLastNameMapping():
model.user.userInfo.lastName = attributeValue
break
case user.getAuthenticationKeyMapping():
model.authenticationValue = attributeValue
break
case user.getEmailMapping():
model.email = attributeValue.toLowerCase()
break
}
The value being switched on (attributeName) is of type String, and the getter methods for the user instance also return type String.
Based on my research and understanding of the Groovy language, switching on an Object such as a String should end up using String.equals() to make the comparison. The result, however, is that it is matching on the user.getFirstNameMapping() case every time, and repeatedly overwriting the value in the model; therefore, the last value that comes back in the response is what ends up saved, and none of the other values are saved.
What's interesting is that if I use an if/else structure and do something like this:
if(attributeName.equals(user.getFirstNameMapping())
{
...
}
It works fine every time. I've verified through logging that it's not something silly like extra whitespace or a capitalization issue. I've also tried changing things around to run the switch by default and explicitly compare the attributeName in the case like this:
switch(true)
{
case {attributeName} :
log.info("Currently switching on value... ${attributeName}")
case {user.getFirstNameMapping().equals(attributeName)}:
model.user.userInfo.firstName = attributeValue
break
case {user.getLastNameMapping().equals(attributeName)}:
model.user.userInfo.lastName = attributeValue
break
case {user.getAuthenticationKeyMapping().equals(attributeName)}:
model.authenticationValue = attributeValue
break
case {user.getEmailMapping().equals(attributeName)}:
model.email = attributeValue.toLowerCase()
break
}
And it still fails to meet my expectations in the exact same way. So, I'm wondering why this is the behavior when the switch statement should simply be using .equals() to compare the strings, and when I explicitly compare them in an if/else using .equals(), it works as expected.
The issue is in your switch case.
Have a look here :-
case {attributeName} :
log.info("Currently switching on value... ${attributeName}")
case user.getFirstNameMapping():
model.user.userInfo.firstName = attributeValue
break
As you can see your these two cases will run every time because the switch condition is :-
switch(attributeName)
So the first one will get match and will run until it encounters break; which is at after case 2 i.e. case user.getFirstNameMapping(): so i would suggest you to print the value of {attributeName} before the swtich starts.
Hope that will help you.
Thanks
I don't know exactly what's your issue, but the case statement works just fine, even with methods. See my example
String something = "Foo"
class User {
String firstName
String lastName
}
User u = new User(firstName: 'Something', lastName:'Foo')
switch(something) {
case u.getFirstName():
println "firstName: ${u.firstName}"
break;
case u.getLastName():
println "lastName: ${u.lastName}"
break;
default:
println "nothing..."
}
This code will print lastName as expected.
​

How to check if the first variable passed into a method is a string. Perl

I have no idea how to check for this. My method(if condition in method) should only work (execute) if the first argument passed in is a string. I know how to check other types, but I can't seem to find anything for checking for a string.
For a hash I would do something like;
if(ref eq 'HASH') {...}
If someone could provide a simple example I'm sure I would be able to apply it to what I'm doing. I will put up the code for the method and an explanation for the whole operational details of the method if needed.
Added Information
This is a method for handling different types of errors in the software, here are the 3 possible input formats:
$class->new("error string message")
$class->new("error string message", code => "UNABLE_TO_PING_SWITCH_ERROR")
$class->new("error string message", code => "UNABLE_TO_PING_SWITCH_ERROR", switch_ip => $ip3, timeout => $timeout)
There will always be an error message string first.
With the 1st case there is also a hashref to an error hash structure that is located in a library,
this method new will go into a template processing if the word "code" exists as an arg. where the longer detailed error message is constructed. (I already have the logic for this).
But I have to add logic so that the error message string is added to the hash, so the output is one hash, and not strings.
The second case is very similar to the first, where there are parameters eg. switch_ip , which are inserted into the string using a similar template processing logic, (already have this too).
So I think the first and second cases can be handled in the same way, but I'm not sure, so separated them in this question.
The last case is just can error message string by itself, which at the minute I just insert it into a one key message hash { message => "error string}.
So after all that how should I be checking or dividing up these error cases, At the minute my idea for the ones with code , is to dump the arguments into a hash and just use something like:
if(exists($param{code}) { doTemplateProcess()...}
I need to ensure that there is a string passed in first though. Which was my original question. Does any of my context information help? I hope I didn't go off the topic of my question, if so I'll open this a new question. Thanks.
Error hash - located in Type.pm
use constant ERROR_CODE => {
UNABLE_TO_PING_SWITCH_ERROR => {
category => 'Connection Error:',
template => 'Could not ping switch %s in %s minutes',
tt => {template => 'disabled'},
fatal => 1,
wiki_page => www.error-solution.com/,
},
}
From comments:
These will be called in the software's code like so
ASC::Builder::Error->new(
"Phase x this occured because y was happening:",
code => UNABLE_TO_PING_SWITCH_ERROR,
switch_ip => $ip3,
timeout => 30,
);
Putting the wisdom of your particular problem aside and channeling Jeff Foxworthy:
If you have a scalar and it's not a reference, you might have a string.
If your non-reference scalar doesn't look like a number, it might be a string.
If your non-reference scalar looks like a number, it can still be a string.
If your non-reference scalar has a different string and number value, it might be a dualvar.
You know that your argument list is just that: a list. A list is a collection of scalar values. A scalar can be a reference or not a reference. I think you're looking for the not a reference case:
die "You can't do that" if ref $first_argument;
Past that, you'd have to do fancier things to determine if it's the sort of value that you want. This might also mean that you reject objects that pretend to be strings through overloading and whatnot.
Perhaps you can make the first argument part of the key-value pairs that you pass. You can then access that key to extract the value and delete it before you use the remaining pairs.
You may easily check only whether the error string is a simple scalar value or a reference. You would do that with ref, but you must consider what you want to do if the first parameter isn't a string
You should write your constructor in the ASC::Builder::Error package along these lines
sub new {
my $class = shift;
my ($error, %options) = #_;
die if ref $error;
bless { string => $error }, $class;
}
This example simply dies, and so kills the program, if it is called with anything other than a simple string or number as the first parameter
You may call it as
ASC::Builder::Error->new('error')
or
ASC::Builder::Error->new(42)
and all will be well. If you try
ASC::Builder::Error->new('message', 'code')
then you will see a warning
Odd number of elements in hash assignment
And you may make that warning fatal
If there is anything more then you should explain
Supporting all of the following is simple:
$class->new("s")
$class->new("s", code => "s")
$class->new("s", code => "s", switch_ip => "s", timeout => "s")
All you need is the following:
sub new {
my ($class, $msg, %opts) = #_;
...
}
You can checks such as the following to examine what the called provided:
if (exists($opts{code}))
if (defined($opts{code}))
if ($opts{code})
Despite saying that the string will always be provided, you now ask how to check if was provided. As such, you are probably trying to perform validation rather than polymorphism. You shouldn't waste your time doing this.
Let's look at the hash reference example you gave. ref($arg) eq 'HASH' is wrong. That returns false for some hash references, and it returns false for some things that act like a reference to a hash. The following is a more proper check:
eval { %$arg; 1 }
The equivalent for strings would be the following:
eval { "$arg"; 1 }
Unfortunately, it will always return true! Every value can act as a string. That means the best thing you can do is simply to check if any argument is provided.
use Carp qw( croak );
croak("usage") if !#_;
It's rare for Perl subs to perform argument validation. Not only is it tricky, it's also expensive. It also provides very little benefits. Bad or missing arguments usually results in exceptions or warnings shortly after.
You might see suggestions to use croak("usage") if ref($arg); (or worse, die if ref($arg);), but keep in mind that those will cause the rejection of perfectly fine objects that overload stringification (which is somewhat common), and they will fail to detect the problem with ASC::Builder::Error->new(code => ...) because code produces a string. Again, performing type-based argument validation is an expensive and buggy practice in Perl.

Spock label combinations

There | are | so many | Spock | spec examples of how to use its labels, such as:
// when -> then label combo
def "test something"() {
when:
// blah
then:
// blah blah
}
Such label combinations as:
when -> then
given -> when -> then
expect
given -> expect
But nowhere can I find documentation on what the legal/meaningful combinations of these labels are. For instance, could I have:
def "do something"() {
when:
// blah
expect:
// blah
}
Could I? I do not know. What about:
def "do something else"() {
when:
// blah
then:
// blah
expect:
// blah
where:
// blah
}
Could I? Again, I do not know. But I wonder.
I am actually an author of one of the tutorials you have mentioned. I think the best to answer your question would be to really understand what particular labels are for. Maybe then it would be more obvious why certain combinations make sense and other do not. Please refer to original documentation http://spockframework.github.io/spock/docs/1.0/spock_primer.html. It explains really well all labels and their purpose. Also it comes with this diagram:
Which I hope should already tell you a lot. So for instance having both when and expect labels makes not much sense. The expect label was designed to substitute both when and then. The reasoning behind it is well explained in the documentation:
An expect block [...] is useful in situations where it is more natural to describe stimulus and expected response in a single expression.
Spock itself will not allow you to use this combination. If you try to execute following code.
def "test"() {
when:
println("test")
expect:
1==1
}
You will receive an error message like this.
startup failed:
/Users/wooki/IdeaProjects/mylibrary/src/test/groovy/ExampleTest.groovy:
13: 'expect' is not allowed here; instead, use one of: [and, then] #
line 13, column 9.
To my surprise the second of your examples works. However I believe there is really not much gain of using expect here instead of and as I would normally do.
def "do something else"() {
when:
// stimulus
then:
// 1st verification
and:
// 2nd verification
where:
// parametrization
}
The only reason to have expect or and after then is to separate code responsible for verifying the result of executing the code inside when label. For instance to group verifications that are somehow related to each other, or even to separate single verifications but to have a possibility of giving them a description using strings that can be attached to labels in Spock.
def "do something else"() {
when:
// stimulus
then: "1 is always 1"
1 == 1
and: "2 is always 2"
2 == 2
}
Hence, since you are already stating that verification part of the test began (using then block) I would stick to and label for separating further code.
Regarding where label. It works sort of as a loop indicator. So whatever combinations of labels you use before you could always put at the end the where label. This one is not really a part of a single test run, it just enforces the test to be run a number of times.
As well it is possible to have something like this:
def "test"() {
given:
def value
when:
value = 1
then:
value == 1
when:
value = 2
then:
value == 2
}
Using the above, just make sure that your test is not "testing too much". Meaning that maybe a reason why you use two groups of when-then makes a perfect excuse for this test to be actually split into two separate tests.
I hope this answered at least some of your questions.

How does DalvikVM handle switch and try smali code

I am trying to learn smali and I have a few question that I couldn't find by googling them.
1) I created a simple test case to better explain myself
const-string v1, "Start"
:try_start_0
const-string v1, "Try Block"
invoke-static {v1}, Lcom/example/test/Main;->print(Ljava/lang/String;)V
:try_end_0
.catchall {:try_start_0 .. :try_end_0} :catchall_0
The .catch statement: does the two arguments mean take from that label to that label and catch it (the code between the two label) or does it mean start executing the try from :try_start_0 up until it reaches :try_end_0 (allows a goto jump to execute code not within the two labels)?
Is the labels for try always in the format try_start_%d or can they be any label?
2)Another case
packed-switch v0, :pswitch_data_0
const-string v1, "Default Case"
invoke-static {v1}, Lcom/example/test/Main;->print(Ljava/lang/String;)V
:goto_0
const-string v1, "The End"
invoke-static {v1}, Lcom/example/test/Main;->print(Ljava/lang/String;)V
return-void
:pswitch_0
const-string v1, "Case 1"
invoke-static {v1}, Lcom/example/test/Main;->print(Ljava/lang/String;)V
goto :goto_0
:pswitch_data_0
.packed-switch 0x1
:pswitch_0
.end packed-switch
The switch statement: Does it require that the switch statements lie between the switch data and the switch call? and also again the naming of the labels fixed or just that for convenience?
3)If the labels can be different, would baksmali ever produce smali code with different labels?
4)What are the optional lines that aren't always shown when decompiling a dex?
I know .parameter and .line are optional, but what are all the ones that might not be there?
Thank you in advance.
1)
The first two labels (try_start_0 and try_end_0 in your example) define the range of code that the try block covers. If an exception happens within the covered code, then execution immediately jumps to the third label (catchall_0). The name of the label isn't important, it can be any valid identifier.
There is also the .catch directive, with is the same thing, except it only handles a specific type of exception (similar to java's catch statement).
A block of code can be covered by multiple catch statements, and at most 1 catch all statement. The location of the .catch statement is not important, however, the relative ordering of catch statements that cover the same code is import. For example, if you have
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :handler1
.catch Ljava/lang/RuntimeException; {:try_start_0 .. :try_end_0} :handler2
The 2nd catch statement will never be used. If a RuntimeException is thrown in the covered code, the first catch will always get used, since a RuntimeException is an Exception.
However, if they were in the opposite order, it would work like you expect - the RuntimeException handler gets used for RuntimeExceptions, and the Exception handler gets used for any other type of exception.
And finally, unlike java, the range of code in the .catch statements does not need to be strictly nested. For example, it's perfectly legal to have something like
:a
const-string v1, "Start"
:b
const-string v1, "Try Block"
:c
invoke-static {v1}, Lcom/example/test/Main;->print(Ljava/lang/String;)V
:d
.catch Ljava/lang/RuntimeException; {:a .. :c} :d
.catch Ljava/lang/Exception; {:b .. :d} :d
You can also have some pretty weird constructions, like this.
.method public static main([Ljava/lang/String;)V
.registers 3
:second_handler
:first_try_start
new-instance v0, Ljava/lang/RuntimeException;
invoke-direct {v0}, Ljava/lang/RuntimeException;-><init>()V
throw v0
:first_try_end
.catch Ljava/lang/Exception; {:first_try_start .. :first_try_end} :first_handler
:first_handler
:second_try_start
new-instance v0, Ljava/lang/RuntimeException;
invoke-direct {v0}, Ljava/lang/RuntimeException;-><init>()V
throw v0
:second_try_end
.catch Ljava/lang/Exception; {:second_try_start .. :second_try_end} :second_handler
.end method
Neither of the above examples would ever be generated from compiled java code, but the bytecode itself allows it.
2) The switch statements could be anywhere in relation to the switch statement or switch data. The label names here are arbitrary as well.
3) Baksmali can generate labels in one of 2 ways. The default way is to use the general "type" of label, and append the bytecode address of the label. If you specify the -s/--sequential-labels option, instead of using the bytecode address, it keeps a counter for each label type and increments it each time it generates a label of that type.
4) Generally anything that is part of the debug information. .parameter, .line, .prologue, .epilogue, .source, .local, .restart local, .end local... I think that about covers it.

Resources