Parsing Options using Apache Commons Library - java

This might be sort of a noob question, but I am using the import org.apache.commons.cli.*; to set up my command line parser application.
This is how I am setting up my option.
Option n = Option.builder().hasArg(true).option("n").build();
options.addOption(n);
In one of our scenarios, we have a particular case where the input looks something like this "-n", "2", "3". Now this is not a valid scenario, because n should fail if you provide more than one value, without the "-n" flag.
Invalid: "-n", "2", "3"
Valid: "-n", "2", "-n", "3"
I was able to get the valid scenario working, but I am unable to get the invalid scenario working. because when I use getOptionValues(), I only get back 2 and not 3. Does anyone know how I can grab 3 too, and fail the invalid scenario.
Thanks.

You can use CommandLine.getArgList() to check for such "trailing" arguments,
CommandLine cmd = parser.parse(options, new String[] {"-n", "2", "3"});
assertTrue(cmd.hasOption(n));
assertEquals("[3]", cmd.getArgList().toString());
So you can fail parsing if cmd.getArgList() is not empty to catch such cases.

Related

Can I create an option name with hyphens in apache commons cli?

I am trying to set Option name with hyphens in it like "source-files" using the Apache Commons CLI java library.
Option option = new Option("source-files", true, "List of source files")
I get this error,
java.lang.IllegalArgumentException: opt contains illegal character value '-'
at org.apache.commons.cli.OptionValidator.validateOption(OptionValidator.java:73)
at org.apache.commons.cli.Option.<init>(Option.java:123)
at org.apache.commons.cli.Option.<init>(Option.java:105)
Which means I cannot use an option name with a hyphen in it, which is the standard with unix commands. I noticed that Commons CLI documentation mentions a hyphenated option name in one their examples. Am I missing something here?
You can only use - in the "long name":
options.addOption("S", "source-files", true, "List of source files")
If you want to only have the long name, you may need to use OptionBuilder (not sure).

WEKA - Multi Class Classification - Can't find class called: weka.classifiers.functions.supportVector.RegSMOImproved

I'm trying to train a MultiClassClassifiermodel in Weka with the base algorithm set to weka.classifiers.functions.supportVector.RegSMOImproved class, with the following options:
MultiClassClassifier cModel = new MultiClassClassifier();
String options[] = {
"weka.classifiers.meta.MultiClassClassifier",
"-M","0",
"-R","2.0",
"-S","1",
"-W","weka.classifiers.functions.supportVector.RegSMOImproved",
"-P","1.0e-12",
"-L","1.0e-3",
"-W","1"
};
try {
cModel.setOptions(options);
} catch (Exception e) {
e.printStackTrace();
}
When I run my code I get the following error:
java.lang.Exception: Can't find class called: weka.classifiers.functions.supportVector.RegSMOImproved
at weka.core.Utils.forName(Utils.java:1073)
at weka.classifiers.AbstractClassifier.forName(AbstractClassifier.java:90)
at weka.classifiers.SingleClassifierEnhancer.setOptions(SingleClassifierEnhancer.java:108)
at weka.classifiers.RandomizableSingleClassifierEnhancer.setOptions(RandomizableSingleClassifierEnhancer.java:93)
at weka.classifiers.meta.MultiClassClassifier.setOptions(MultiClassClassifier.java:802)
at myApp.Main.trainMultiClassClassifier(Main.java:983)
at myApp.Main.createSets(Main.java:903)
at myApp.Main.main(Main.java:387)
What is the correct class path for use of RegSMOImproved algorithm if not weka.classifiers.functions.supportVector.RegSMOImproved?
Am I missing something else here, an additional setting perhaps, or some kind of a parent class?
I'm using Weka developer-branch from here. If there is anything I left out unintentionally please let me know and I'll make an edit asap.
Thank You in advance.
EDIT 1:
I'm trying to accomplish multi class classification where I would train my model/models as one class vs. the rest. My data is balanced (100 samples per class). This is what I've found so far:
http://weka.8497.n7.nabble.com/meta-multi-class-classifier-with-the-option-smo-td26548.html
EDIT 2:
So I've changed my options object to:
String options[] = {
"-M","0",
"-R","2.0",
"-S","1",
"-W","weka.classifiers.functions.SMO",
"--",
"-C","1",
"-L","0.001",
"-P","1.0e-12",
"-M",
"-N", "0",
"-V","-1",
"-W","1",
"-K", "weka.classifiers.functions.supportVector.PolyKernel -C 250007 -E 1.0"
};
This seems to go through setOptions(), so I've clearly mixed the two SMO classes from supportVector and functions packages. I've also read that I need to set the -M and -V properties for SMO in order for my MultiClassClassifier to work correctly. So I've turned on "fitting calibration models to SVM outputs" with the -M property and I've set the number of folds for cross validation to -1 (default) with the -V property.
I assume the number of folds property for cross validation has to be set for testing purposes. Will have to check out posts on cross validation from this point.
Thank You again!
A) you probably shouldn't be using the developer branch unless you have a specific need. For all we know they are moving stuff around and its potentially broken
B) RegSMOImproved is for Regression , not classification. So some of your issues could be that miss match between the MultiClassClassifier and a regression algorithm.

Using Apache common-cli to parse arguments

Apache common-cli has a example on its web site for ls command:
options.addOption( "a", "all", false, "do not hide entries starting with ." );
options.addOption( "A", "almost-all", false, "do not list implied . and .." );
options.addOption( "b", "escape", false, "print octal escapes for nongraphic " + "characters" );
options.addOption( OptionBuilder.withLongOpt( "block-size" )
.withDescription( "use SIZE-byte blocks" )
.hasArg()
.withArgName("SIZE")
.create() );
This shows help like this:
-a, --all do not hide entries starting with .
-A, --almost-all do not list implied . and ..
-b, --escape print octal escapes for nongraphic characters
--block-size=SIZE use SIZE-byte blocks
When I write this code, it shows --block-size <SIZE>. I want to show something like this: -z,--block-size=SIZE(not just
long option).
what is the difference of PosixParser and GnuParser? I changed
them in the code, I didn't observed any difference.
When I provide wrong option for example h it doesn't throw any ParseException. The program starts and finishes normally.
The block size option in the example has only a long format, that's why there is no short option shown. If you add a short alias you'll get the result you expect
PosixParser and GnuParser are deprecated in the latest version of Commons CLI. A new unified parser is available as DefaultParser. The posix parser had the ability to parse concatenated short options, something like tar -zxvf foo.tar.gz.
Extra options are either handled as arguments to the application or trigger an exception, depending of the value of the stopAtNonOption parser parameter.

How do I submit a JSON to SOLR using Zend_Client?

How do I submit a JSON to SOLR using Zend_Client?
Assume the JSON I am using is (It was taken from the SOLR WIKI, so I assume it is right).
$JSON ='[{"id" : "3", "title" : "test3","description":"toottoto totot ototot "}]';
I see no error in the solr error log, this is the code I use to submit
DOES NOT WORK
$url = 'http://localhost:8983/solr/update/json';
$Client = new Zend_Http_Client($url);
$Client->resetParameters();
$Client->setMethod(Zend_Http_Client::POST);
$Client->setHeaders('Content-type','application/json');
$Client->setParameterPost($JSON);//***** WRONG *****
$Client->setRawData($JSON); //* **** RIGHT FROM ANSWER BELOW, STILL NEED TO ENCODE IT!
$response = $Client->request();
THIS WORKS FROM THE COMMAND LINE!
sudo curl http://localhost:8983/solr/update/json -H 'Content-type:application/json' -d '
[{"id" : "3", "title" : "test3","description":"toottoto totot ototot "}]'
The setParameterPost() method takes two arguments, the parameter name and its value like this:
$client->setParameterPost('name', 'john'); // results in name=john
Try using setRawData() instead, this will let you set raw post data.

How to log formatted message, object array, exception?

What is the correct approach to log both a populated message and a stack trace of the exception?
logger.error(
"\ncontext info one two three: {} {} {}\n",
new Object[] {"1", "2", "3"},
new Exception("something went wrong"));
I'd like to produce an output similar to this:
context info one two three: 1 2 3
java.lang.Exception: something went wrong
stacktrace 0
stacktrace 1
stacktrace ...
My SLF4J version is 1.6.1.
As of SLF4J 1.6.0, in the presence of multiple parameters and if the last argument in a logging statement is an exception, then SLF4J will presume that the user wants the last argument to be treated as an exception and not a simple parameter. See also the relevant FAQ entry.
So, writing (in SLF4J version 1.7.x and later)
logger.error("one two three: {} {} {}", "a", "b",
"c", new Exception("something went wrong"));
or writing (in SLF4J version 1.6.x)
logger.error("one two three: {} {} {}", new Object[] {"a", "b",
"c", new Exception("something went wrong")});
will yield
one two three: a b c
java.lang.Exception: something went wrong
at Example.main(Example.java:13)
at java.lang.reflect.Method.invoke(Method.java:597)
at ...
The exact output will depend on the underlying framework (e.g. logback, log4j, etc) as well on how the underlying framework is configured. However, if the last parameter is an exception it will be interpreted as such regardless of the underlying framework.
In addition to #Ceki 's answer, If you are using logback and setup a config file in your project (usually logback.xml), you can define the log to plot the stack trace as well using
<encoder>
<pattern>%date |%-5level| [%thread] [%file:%line] - %msg%n%ex{full}</pattern>
</encoder>
the %ex in pattern is what makes the difference
The accepted answer is great. I'm just adding here my case that is now working thanks for the answer. This may help someone else.
I'm using SLF4J and logback with a JSON encoder. Furthermore, I use marker and arguments to enrich my output.
logger.error(getMarker("errorEvent"),
"An error occurred",
entries(mapOf("someKey" to "someValue")),
new Exception())
The output:
{
"level": "ERROR",
"event": "errorEvent",
"eventData": {
"someKey": "someValue"
},
"stacktrace": "...omitted...",
"message": "An error occurred"
}
Of course there is a lot of configuration of logstash behind the scenes, but I just wanted to show that the arguments passed as entries are shown in the configured eventData tag.

Categories

Resources