Using Groovy CliBuilder, ideally I would like to have an cmd-line as follows:
./MyProgram.groovy CommandName -arg1 -arg2 -arg3
Is is possible to parse pull out the CommandName as an argument using CliBuilder?
You can do that if you set the property stopAtNonOption to false so that the parsing does not stop in CommandName. Then you can get the command from CliBuilder options. A tiny example below:
def test(args) {
def cli = new CliBuilder(usage: 'testOptions.groovy [command] -r -u', stopAtNonOption: false)
cli.with {
r longOpt: 'reverse', 'Reverse command'
u longOpt: 'upper', 'Uppercase command'
}
def options = cli.parse(args)
def otherArguments = options.arguments()
def command = otherArguments ? otherArguments[0] : 'defaultCommand'
def result = command
if (options.r) {
result = result.reverse()
}
if (options.u) {
result = result.toUpperCase()
}
result
}
assert 'myCommand' == test(['myCommand'])
assert 'MYCOMMAND' == test(['myCommand', '-u'])
assert 'dnammoCym' == test(['myCommand', '-r'])
assert 'DNAMMOCYM' == test(['myCommand', '-r', '-u'])
assert 'defaultCommand' == test([])
Related
I'm using JIB (not super relevant) and I want to pass in variables from command line in my deployment script.
I append using -PinputTag=${DOCKER_TAG} -PbuildEnv=nonprod in my gradle command, which is cool. But when it's missing, I want that ternary to kick in.
I'm getting the error:
Could not get unknown property 'inputTag' for project ':webserver' of type org.gradle.api.Project.
def inputTag = inputTag ?: 'latest'
def buildEnv = buildEnv ?: 'nonprod'
jib {
container {
mainClass = 'com.example.hi'
}
to {
image = 'image/cool-image'
tags = ['latest', inputTag]
}
container {
creationTime = 'USE_CURRENT_TIMESTAMP'
ports = ['8080']
jvmFlags = ['-Dspring.profiles.active=' + buildEnv]
}
}
Found Solution
def inputTag = project.hasProperty('inputTag') ? project.property('inputTag') : 'latest'
def buildEnv = project.hasProperty('buildEnv') ? project.property('buildEnv') : 'nonprod'
This seems to be working, is this the best way?
How about this?
image = 'image/cool-image:' + (project.findProperty('inputTag') ?: 'latest')
Note jib.to.tags are additional tags. jib.to.image = 'image/cool-image' already implies image/cool-image:latest, so no need to duplicate latest in jib.to.tags.
spark.sqlContext.udf.register('dataSource', (data: scala.collection.mutable.WrappedArray$ofRef, ofType : String) => {
var flag = ''
try{
val array: Seq[String] = data.flatten(x => Seq(x.toString()))
array.foreach(s => if(s.contains(ofType)) { flag = ofType })
}
catch {
println("Exception :" + x.getMessage)
flag = ''
}
flag;
})
It is not required to convert this Scala code into Java code. In Spark you can register a UDF in any of the languages and also make use of it in either Java or Scala as long as it is used in the same SparkSession or Context.
I have an app that I wanted to customize using some sort of expression evaluator.
I wanted to change certain parts of the app without recompiling my code.
I am thinking of using groovy expression.
Say for example, I have a feature that can be enabled/disabled by supplying expression:
In this case, this feature will be enabled
Example 1:
EXPRESSION : status = part-time || status = hourly
INPUT: status = part-time
In this case, this feature will be disabled
Example 2:
EXPRESSION : status = part-time || status = hourly
INPUT: status = permanent
Users are required to enter an expression and an Input. Expression should evaluate to a boolean expression
They can also change the expression and the program will pick up this by some evaluation.
These expressions by the way are documented and is exposed by me to the user of my application
Example 3:
EXPRESSION : salary > 10000
INPUT: salary = 7000
I have seen a program before that does this and they say that they uses groovy under the hood.
But I cannot get my head wrap around the concept.
Can somebody please give me an idea?
Alternative approach using evaluate. Your variables are defined in binding, evaluate contains the expression:
// setup binding
def emp = [status:'permanent', name:'Hugo']
def binding = new Binding()
binding.status = 'permanent'
binding.status2 = 'part-time'
binding.salary = 7000
binding.employee = emp
println binding.variables
// evaluate the script
def ret = new GroovyShell(binding).evaluate("status == 'part-time' || status == 'hourly'")
println ret
ret = new GroovyShell(binding).evaluate("status2 == 'part-time' || status2 == 'hourly'")
println ret
ret = new GroovyShell(binding).evaluate("salary > 10000")
println ret
ret = new GroovyShell(binding).evaluate("employee.status == 'permanent' || employee.status == 'hourly'")
println ret
returns
[status:permanent, status2:part-time, salary:7000, employee:[status:permanent, name:Hugo]]
false
true
false
true
the usual call of groovy script:
import groovy.lang.Binding;
import groovy.lang.Script;
import groovy.lang.GroovyShell;
Binding binding = new Binding();
binding.setProperty("status", "part-time");
GroovyShell shell = new GroovyShell(binding);
Script script = shell.parse(" status == 'part-time' || status == 'hourly' ");
Object result = script.run();
after run the binding will be populated with new values of the variables.
you can cache the parsed script (or class of the parsed script) because parsing/compiling is expensive process.
as alternative - the easiest script evaluation:
Object result = groovy.util.Eval.me("status", "part-time",
" status == 'part-time' || status == 'hourly' ");
Let's say I have a function
writeToFileOrStdout(fname: String = Nil) = { ... }
If the user passes a string value for fname, then I'd like to open a file with that name and write to it; otherwise, I'd like to print to stdout. I could always just write an if statement to take care of this, but how would I write a case statement on fname and open the correct corresponding outputStream?
val outStream = fname match {
case Nil => ???
case _ => new java.io.FileOutputStream(new java.io.File(fname))
}
outStream.write( ... )
Thanks!
Why not rewrite the function as:
def writeToFileOrStdout(fname: Option[String] = None) = {
val outStream = fname match{
case Some(name) => new java.io.FileOutputStream(new java.io.File(name))
case None => System.out
}
...
}
It's always a good idea to use Option for an optional input as opposed to using null. That's basically what it's there for. In good scala code, you will not see explicit references to null.
In fact, your code doesn't even compile for me. Nil is used to represent an empty list, not a null or non supplied String.
To augment cmbaxter's response...
Mapping a String with a possible null value to Option[String] is trivial: Option(stringValue) will return None where stringValue is null, and Some(stringValue) where non-null.
Thus, you can either:
writeToFileOrStdout(Option(stringValue)), or
If you're stuck on String (and possibly a null value) as the parameter to writeToFileOrStdout, then internally use Option(fname) and match to what it returns::
def writeToFileOrStdout(fname: String = null) = {
val outStream = Option(fname) match{
case Some(name) => new java.io.FileOutputStream(new java.io.File(name))
case None => System.out
}
...
}
To further augment cmbaxter's response, you might consider writing this:
def filenameToOutputStream(name: String) =
new java.io.FileOutputStream(new java.io.File(name))
def writeToFileOrStdout(fname: Option[String] = None) = {
val outStream = fname map filenameToOutputStream getOrElse System.out
...
}
As the post Idiomatic Scala: Your Options Do Not Match suggests, this might be more idiomatic Scala.
Can anyone assist me on how do I load the object FooBar dynamically and call the roquet function (dynamically) ?
I have this snippet in Perl:
#!/usr/bin/perl -w
use Inline Java => << 'End_Of_Java_Code';
class FooBar {
public FooBar(){}
public void roquet() {
System.out.println("HELLO!");
}
}
End_Of_Java_Code
use Data::Dumper;
use Class::Sniff;
my $sniff = Class::Sniff->new({class=>'FooBar'});
my $num_methods = $sniff->methods;
my $num_classes = $sniff->classes;
my #methods = $sniff->methods;
my #classes = $sniff->classes;
my #unreachable = $sniff->unreachable;
foreach my $method (#methods) {
if ( $method eq "roquet" ) {
print "$method\n";
}
}
I tried the following approaches and variations:
a. approach:
use Module::Load
my $package = "main::FooBar";
load $package;
$package->new();
$package->$rflmethod;//where rflmethod is the variable: $rflmethod='roquet';
b. approach:
no strict 'refs';
use Package::Stash;
my $stash = Package::Stash->new('main::FooBar');
my $coderef = $stash->get_symbol('&__new');
$coderef->()
This works:
my ($class, $method) = qw(FooBar roquet);
my $f = $class->new;
$f->$method;