split config sources cleanly with json nesting

This commit is contained in:
Jonathan Shook 2022-02-08 15:10:08 -06:00
parent 4fd1a5bdd7
commit 273b42e2ee
2 changed files with 132 additions and 0 deletions

View File

@ -0,0 +1,99 @@
package io.nosqlbench.nb.api.config.standard;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
public class NBConfigSplitter {
private enum State {
any,
json, escaped
}
/**
* Split off any clearly separate config loader specifications from the beginning or end,
* so they can be composed as an ordered set of config loaders.
*
* @param configs The string containing driver config specs as described in the cqld4.md
* documentation.
* @return A list of zero or more strings, each representing a config source
*/
// for testing
public static List<String> splitConfigLoaders(String configs) {
LinkedList<State> states = new LinkedList<>();
List<String> elements = new ArrayList<>();
StringBuilder element = new StringBuilder();
states.push(State.any);
for (int i = 0; i < configs.length(); i++) {
State state = states.peek();
Objects.requireNonNull(state);
char c = configs.charAt(i);
if (state == State.escaped) {
element.append(c);
states.pop();
} else if (c == '\\') {
states.push(State.escaped);
continue;
}
switch (state) {
case any:
if (c == ',') {
elements.add(element.toString());
element.setLength(0);
} else if (c == '{') {
states.push(State.json);
element.append(c);
} else {
element.append(c);
}
break;
case json:
if (c == '{') {
states.push(State.json);
element.append(c);
} else if (c == '}') {
states.pop();
element.append(c);
} else {
element.append(c);
}
}
}
if (element.length()>0) {
elements.add(element.toString());
}
// List<String> configs = new ArrayList<>();
// Pattern preconfig = Pattern.compile("(?<pre>(\\w+://.+?)|[a-zA-z0-9_:'/\\\\]+?)\\s*,\\s*(?<rest>.+)");
// Matcher matcher = preconfig.matcher(configs);
// while (matcher.matches()) {
// configs.add(matcher.group("pre"));
// configs = matcher.group("rest");
// matcher = preconfig.matcher(configs);
// }
// Pattern postconfig = Pattern.compile("(?<head>.+?)\\s*,\\s*(?<post>(\\w+://.+?)|([a-zA-Z0-9_:'/\\\\]+?))");
// matcher = postconfig.matcher(configs);
// LinkedList<String> tail = new LinkedList<>();
// while (matcher.matches()) {
// tail.push(matcher.group("post"));
// configs = matcher.group("head");
// matcher = postconfig.matcher(configs);
// }
// if (!configs.isEmpty()) {
// configs.add(configs);
// }
// while (tail.size() > 0) {
// configs.add(tail.pop());
// }
// return configs;
return elements;
}
}

View File

@ -0,0 +1,33 @@
package io.nosqlbench.nb.api.config.standard;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class NBConfigSplitterTest {
@Test
public void testSplitConfigs() {
List<String> strings = NBConfigSplitter.splitConfigLoaders("http://config.example.com/asdf,file:foo,{inline config},c://file,/tmp/test");
assertThat(strings).containsExactly(
"http://config.example.com/asdf",
"file:foo",
"{inline config}",
"c://file",
"/tmp/test"
);
}
@Test
public void testSplitConfigs2() {
List<String> strings = NBConfigSplitter.splitConfigLoaders("http://config.example.com/asdf,{\"inline1\":\"config1\"},{\"inline2\":\"config2\"}");
assertThat(strings).containsExactly(
"http://config.example.com/asdf",
"{\"inline1\":\"config1\"}",
"{\"inline2\":\"config2\"}"
);
}
}