Reputation: 1223
I have a ws.properties file in which there's a property called success.code that gives me the option the choose which HTTP Status success codes (2xx), aside from the default 200, I want the server to treat as "Success" as well.
The idea is like this:
success.code=201,202, 203 (values separated by a comma)
The part of the code responsible for extracting this value should immediately understand that these are three separate codes, extract each one of them and store them in a list or set or....
This is actually pretty easy:
private Set<String[]> getSuccessCodes(HashMap<String, String> codes){
Set<String[]> successCodes = new HashSet<>();
String value;
for (Map.Entry<String, String> entry : codes.entrySet()) {
value = entry.getValue();
if(!StringUtils.isEmpty(value))
successCodes.add(value.split("\\s*,\\s*"));
}
return successCodes;
}
I would also like to add these options as well:
success.code=[202, 220] (two values written between hooks and separated by a comma)
success.code=2**
success.code=[200, 205], 22*
So depending on the value that I enter for the success code, the program should be able to understand what to do and what to return from it.
Is this achievable?
Thanks in advance
Upvotes: 2
Views: 74
Reputation: 16498
If you don't mind adding three more methods, here is one approach:
"\\s*,\\s*(?![^\\[]*\\])"
to split at each comma unless in brackets[
or *
[
generate an IntStream.rangeClosed(x,y)
using the values in [x,y]
and map them to their string values*
generate an IntStream.rangeClosed(x00,x99)
by replacing *
with 0
and 9
and map them to their string valuesSomething like:
private static Set<String[]> getSuccessCodes(HashMap<String, String> codes){
Set<String[]> successCodes = new HashSet<>();
String value;
for (Map.Entry<String, String> entry : codes.entrySet()) {
value = entry.getValue();
if(!StringUtils.isEmpty(value))
successCodes.add(parse(value));
}
return successCodes;
}
public static String[] parse(String val) {
String[] parts = val.split("\\s*,\\s*(?![^\\[]*\\])");
return Arrays.stream(parts)
.map(e -> e.contains("[")? getRangeCodes(e): e.contains("*")? getWildCCodes(e): e)
.collect(Collectors.joining(",")).split("\\s*,\\s*");
}
private static String getRangeCodes(String e) {
e = e.substring(1, e.length()-1);
return IntStream.rangeClosed(Integer.parseInt(e.split("\\s*,\\s*")[0]), Integer.parseInt(e.split("\\s*,\\s*")[1]))
.mapToObj(i -> String.valueOf(i))
.collect(Collectors.joining(","));
}
private static String getWildCCodes(String e) {
return IntStream.rangeClosed(Integer.parseInt(e.replace('*', '0')), Integer.parseInt(e.replace('*', '9')))
.mapToObj(i -> String.valueOf(i))
.collect(Collectors.joining(","));
}
Tested with:
public static void main(String[] args) {
HashMap<String, String> codes = new HashMap<>();
codes.put("foo", "201, 202, 203");
codes.put("bar", "[202, 220]");
codes.put("baz", "2**");
codes.put("doo", "[200, 205], 22*");
codes.put("woo", "200, 201, 202, 203,[209, 214], 29*");
Set<String[]> set = getSuccessCodes(codes);
set.forEach(s -> {System.out.println(Arrays.toString(s));});
}
Upvotes: 1
Reputation: 652
Instead of requiring your program to accept some elaborate grammar that you defined, why not let the framework do what it does naturally?
success.codes = 201,202,203
success.code.min = 202
success.code.max = 220
success.code.prefix = 22
Then combine these properties in your code as you see fit. This is the easiest way to achieve what you want.
Upvotes: 0
Reputation: 7808
First of all, the answer is definitely yes it is achievable. The solution would be that you will have to write your own parser or mini-interpreter that would take your String and first "compile" it - i.e. check that it is a valid input (say that number of "[" is equal to number of "]" and that at no point while parsing the number of "]" is not greater then number of "]" i.e. String "[...]][" should be declared invalid). And then it would interpret it. The more flexible you want your language to be the more complex your interpreter would be. Most likely Regular expressions won't be enough. But in general you will need to write a method with signature like this:
Set<Integer> parseHttpCodesParam(String input);
Your implementation will have several rules
etc
Upvotes: 0