How can I get the input order of parameters in JCommander?
I want to know which parameter was input first.
For example
Myapp --cut -- reverse
Myapp --reverse -- cut
Is this possible in Jcommander?
And if so, how?
One way to achieve your need is instead of define multiple flag.
See Arities (multiple values for parameters)
Then read your command args:
#Parameter(names = "-cmd", variableArity = true)
public List<String> commands= new ArrayList<>();
MyApp -cmd cut reverse -anotherCmd
Related
I've a value object(VO). One of the field/property is 'sourceKey' that holds a string value.
For Example:
String sourceKey1 = "cust12/proj1/site1/images/somefile.JPG"
String sourceKey2 = "cust12/area1/site1/images/somefile.JPG"
Now I need to kinda transform this sourceKey and build up a destination key by first breaking the source key by'/' and then:
- replace cust12 by calling customer service - find customer by Id 12 and replace cust12 by customer name in the dest key.
- similarly to replace proj1 - call the project service , find project by id 1 and replace proj1 by the project name.
- and so on..
So to achieve this in a clean manner, I thought of writing commands - each command for fetching an object by calling the appropriate service(customerService, projectService etc). And then at the client level just parse the sourceString and build up a list of commands to be executed and then finally build up a destination key using the commands list.
Am I thinking in the right direction? Is command pattern the clean/OO way of doing this?
No, the Command Pattern is not suited to this problem. From an OOP perspective, I would start by modeling the source key as an Object rather than a String, to avoid stringly-typed programming.
It looks like a SourceKey object would have dependencies on CustomerService and ProjectService, and would contain five fields, which it can combine into a String as necessary. In other words, try encapsulating the String transformation logic into its own Object.
I am reading a property file in Java.
Properties myProp = new Properties();
InputStream in = new FileInputStream(pathOfPropertyFile);
myProp.load(in);
in.close();
The values in the property file have references to Linux shell variables.
For example, an entry in the property file might look like:
DATA_PATH=/data/${PROJECT}/${YEAR}${MONTH}${DAY}
I have to execute a shell script from java and so I have ProcessBuilder instance and also the environment variables (envMap as given below):
List<String> command = new ArrayList<String>();
command.add(actualCommand);
command.add(param1);
command.add(param2);
ProcessBuilder processBuilder = new ProcessBuilder(command);
Map<String, String> envMap = processBuilder.environment();
The envMap has the environment variables I require along with over one hundred (> 100) other environment variables which I do not require.
I want to replace the ${USER},${PROJECT},etc., from the property-value string "/home/${USER}/${PROJECT}/data" with actual values from the shell.
I would consider iterating the Map as the last option(as the Map has between 100 and 200 elements to iterate) as it is not an efficient approach.
Please advise some approach that will fetch the environment variable enclosed by braces from the string, so that I can directly use the get() of the Map and replace. Or, any better approaches are most welcome.
Note: The reference offered ( Replace String values with value in Hash Map that made my question to look duplicate) is not the best fit in my case.
If you are open to using an external library, StrSubstitutor from apache-commons will do exactly what you want:
public static void main(String[] args) {
String input = "DATA_PATH=/data/${PROJECT}/${YEAR}${MONTH}${DAY}";
Map<String, String> env = new HashMap<>();
env.put("PROJECT", "myProject");
env.put("YEAR", "2017");
env.put("MONTH", "7");
env.put("DAY", "5");
env.put("OTHER_VALUE", "someOtherValue");
System.out.println(StrSubstitutor.replace(input, env));
}
Output:
DATA_PATH=/data/myProject/201775
It also has a method to directly replace system properties without the need for an explicit map.
(for a non-external-library approach see vefthym's answer)
I am not sure if it works, but I hope someone can edit to make it work, or at least you get the logic and make it work on your own:
command = command.replaceAll("\\$\\{(.*?)\\}", envMap.get("$1"));
Here, I am assuming that command is a String (not a List) and that all environment variables exist in your Map (otherwise you should check for null and handle this case as you wish).
A bit of an explanation:
this regex is looking for the pattern "${something}" and replaces it with envMap.get("something"). In this example, we use parentheses to mark "something" as a group, which can then be retracted as "$1" (since we have only one group, i.e., only one set of parentheses).
The question mark '?' is the non-greedy operator here meaning to stop at the smallest possible regex match (otherwise it would find a singe match for the first "${" until the last "}".
I'm using the Play Framework (Java) and am not able to figure out how to use environment variables in my configuration file for building the database connection string. While I'm able to use environment variables like this (for user name and password):
default.username = ${?FU_MAIN_DB_USERNAME}
default.password = ${?FU_MAIN_DB_PASSWORD}
I'm not able to make it work in the url string. Perhaps this is a simple case of string processing in Scala that I'm missing, but since I'm working in Java, I could use some help.
So far, I have tried the url string in the following formats and failed:
Tried to add a $ to variable name to perform interpolation:
default.url = "jdbc:postgresql://$${?FU_MAIN_DB_HOST}:$${?FU_MAIN_DB_PORT}/$${?FU_MAIN_DB_NAME}";
But this doesn't substitute. Rather, it picks the string as such.
default.url = "jdbc:postgresql://${?FU_MAIN_DB_HOST}:${?FU_MAIN_DB_PORT}/${?FU_MAIN_DB_NAME}";
This too inserts the '$' and all verbatim. Then I thought maybe something like PHP-style will work
default.url = "jdbc:postgresql://${${?FU_MAIN_DB_HOST}}:${${?FU_MAIN_DB_PORT}}/${${?FU_MAIN_DB_NAME}}";
But no.
I also tried doing stuff like "jdbc:postgresql://".concat(${?FU_MAIN_DB_HOST}) ... but this also inserts '.concat' verbatim.
Finally, I tried concatenation using the '+' operator, but I'm told (by my IDE) that symbols like +: etc. are not allowed in the application.conf file.
How then, in God's name, am I supposed to do that?!
The double quotes turn off interpolation. But you need to do that for the : and the //.
Try
default.url = "jdbc:postgresql://"${?FU_MAIN_DB_HOST}":"${?FU_MAIN_DB_PORT}/${?FU_MAIN_DB_NAME}
Maybe you are better off to set the whole thing in one big environment variable instead.
How to filter a list/collection of streams based on url parameters, for example:
?filter=(type=="audio"&&systemBitrate<100000)||(type=="video"&&systemBitrate<1024000)
I know this can be done using statically:
List<StreamItem> results = streamList.stream().filter(s -> s.type == "audio" && s.systemBitrate < 100000).collect(Collectors.toList());
Simple object:
public class StreamItem {
String name;
String type;
int systemBitrate;
}
The idea is to dynamically filter playback manifest in a similar way to the one below and play only selected tracks:
curl -v 'http://demo.unified-streaming.com/video/tears-of-steel/tears-of-steel.ism/Manifest?filter=(type=="audio"%26%26systemBitrate<100000)||(type=="video"%26%26systemBitrate<1024000)'
One way to do it is to use one of the "Expression Language" libraries,
to compile your filter expression and then apply it to the elements of your stream.
Below is a short example using MVEL:
pom.xml
<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
<version>2.3.1.Final</version>
</dependency>
java code
Serializable expr = MVEL.compileExpression(
"(type==\"audio\"&&systemBitrate<100000)||(type==\"video\"&&systemBitrate<1024000)"
);
Arrays.asList(
new StreamItem("audio",10000),
new StreamItem("audio",200000),
new StreamItem("video",200000),
new StreamItem("video",2000000)
)
.stream()
.filter(e->MVEL.executeExpression(expr,e,boolean.class))
.forEach(System.out::println);
output
Element{type='audio', systemBitrate=10000}
Element{type='video', systemBitrate=200000}
Please note that your StreamItem class must have getters defined for both type and systemBitrate properties, for the MVEL to be able to resolve them.
Don't expect this to be blazing fast, yet it still should be fast enough for most practical tasks, taking that expression is compiled, before use.
Filtering a list of 1000000 (one million) StreamItems, using the expression above, takes ~150ms on my laptop, on average.
I'm trying to get a regex that can pull out the flags and values in string. Basically, I need to be able to take a string like this:
command -aparam -b"Another \"quoted\" param" -canother one here
And capture the data:
a param
b Another "quoted" param
c another one here
Here is my Java regex so far:
(?<= -\w)(?:(?=")(?:(?:")([^"\\]*(?:\\.[^"\\]*)*)(?="))|.*?( -\w|$))?
But is doesn't quite work yet. Any suggestions?
The suggestion is to use one of available CLI parsers. For example CLI from Jakarta or, better, args4j.
Tokenize the string into command and its parameters using split method,
String input = "command -aparam -b\"Another \"quoted\" param\" -canother one here ";
String[] cmds = input.split("\\s*-(?=\\w)");