support anonymous bindings in bindpoints

This commit is contained in:
Jonathan Shook
2021-06-24 11:10:12 -05:00
parent fdbace26cd
commit 46c095d9cb
3 changed files with 110 additions and 26 deletions

View File

@@ -5,14 +5,38 @@ import java.util.Objects;
public class BindPoint {
private final String anchor;
private final String bindspec;
private final Type type;
public enum Type {
/**
* a reference bindpoint is expressed as a single word within single curly braces like <pre>{@code {bindref}}</pre>
*/
reference,
/**
* a definition bindpoint is expressed as anything between double curly braces like <pre>{@code {{Identity()}}</pre>
*/
definition
}
public BindPoint(String anchor, String bindspec, Type type) {
this.anchor = anchor;
this.bindspec = bindspec;
this.type = type;
}
public BindPoint(String anchor, String bindspec) {
this.anchor = anchor;
this.bindspec = bindspec;
this.type=Type.reference;
}
public static BindPoint of(String userid, String bindspec) {
return new BindPoint(userid,bindspec);
public static BindPoint of(String userid, String bindspec, Type type) {
return new BindPoint(userid,bindspec,type);
}
public Type getType() {
return type;
}
public String getAnchor() {
@@ -27,23 +51,21 @@ public class BindPoint {
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BindPoint bindPoint = (BindPoint) o;
if (!Objects.equals(anchor, bindPoint.anchor)) return false;
return Objects.equals(bindspec, bindPoint.bindspec);
return Objects.equals(anchor, bindPoint.anchor) && Objects.equals(bindspec, bindPoint.bindspec) && type == bindPoint.type;
}
@Override
public int hashCode() {
return Objects.hash(anchor, bindspec);
return Objects.hash(anchor, bindspec, type);
}
@Override
public String toString() {
return "BindPoint{" +
"anchor='" + anchor + '\'' +
", bindspec='" + bindspec + '\'' +
'}';
"anchor='" + anchor + '\'' +
", bindspec='" + bindspec + '\'' +
", type=" + type +
'}';
}
}

View File

@@ -4,38 +4,88 @@ import io.nosqlbench.nb.api.errors.BasicError;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BindPointParser implements Function<String, List<String>> {
public class BindPointParser implements BiFunction<String, Map<String,String>, BindPointParser.Result> {
public final static Pattern BINDPOINT_ANCHOR = Pattern.compile("(\\{((?<anchor>\\w+[-_\\d\\w.]*)})|(\\{\\{(?<extended>[^}]+)}}))");
public final static String DEFINITION = "DEFINITION";
@Override
public List<String> apply(String template) {
public Result apply(String template, Map<String,String> bindings) {
Matcher m = BINDPOINT_ANCHOR.matcher(template);
int lastMatch = 0;
List<String> spans = new ArrayList<>();
List<BindPoint> bindpoints = new ArrayList<>();
while (m.find()) {
String pre = template.substring(lastMatch, m.start());
lastMatch=m.end();
spans.add(pre);
lastMatch=m.end();
String anchor = m.group("anchor");
if (anchor == null) {
anchor = m.group("extended");
if (anchor == null) {
throw new BasicError("Unable to parse: " + template);
}
String extendedAnchor = m.group("extended");
if (anchor!=null) {
bindpoints.add(BindPoint.of(anchor, bindings.getOrDefault(anchor, null), BindPoint.Type.reference));
spans.add(anchor);
} else if (extendedAnchor!=null) {
bindpoints.add(BindPoint.of(DEFINITION,extendedAnchor, BindPoint.Type.definition));
spans.add(extendedAnchor);
} else {
throw new BasicError("Unable to parse: " + template);
}
spans.add(anchor);
}
spans.add(lastMatch >= 0 ? template.substring(lastMatch) : template);
return spans;
return new Result(spans,bindpoints);
}
public final static class Result {
private final List<String> spans;
private final List<BindPoint> bindpoints;
public Result(List<String> spans, List<BindPoint> bindpoints) {
this.spans = spans;
this.bindpoints = bindpoints;
}
public List<String> getSpans() {
return spans;
}
public List<BindPoint> getBindpoints() {
return bindpoints;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Result result = (Result) o;
return Objects.equals(spans, result.spans) && Objects.equals(bindpoints, result.bindpoints);
}
@Override
public int hashCode() {
return Objects.hash(spans, bindpoints);
}
@Override
public String toString() {
return "Result{" +
"spans=" + spans +
", bindpoints=" + bindpoints +
'}';
}
}
}

View File

@@ -2,21 +2,33 @@ package io.nosqlbench.virtdata.core.templates;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
public class BindPointParserTest {
@Test
public void testBindPointParser() {
public void testSingleRefTypeBindPoint() {
BindPointParser bpp = new BindPointParser();
assertThat(bpp.apply("test {one}")).containsExactly("test ","one","");
assertThat(bpp.apply("test {one} {{two three}}")).containsExactly("test ","one"," ","two three","");
assertThat(bpp.apply("test {one}", Map.of())).isEqualTo(
new BindPointParser.Result(
List.of("test ","one",""),
List.of(BindPoint.of("one",null, BindPoint.Type.reference)))
);
// assertThat(bpp.apply("test {one} {{two three}}",Map.of())).containsExactly("test ","one"," ","two three","");
}
@Test
public void testBindPointParserBypass() {
public void testSingleDefinitionTypeBindPoint() {
BindPointParser bpp = new BindPointParser();
assertThat(bpp.apply("")).containsExactly("");
assertThat(bpp.apply("test {{this is a definition}}", Map.of())).isEqualTo(
new BindPointParser.Result(
List.of("test ","this is a definition",""),
List.of(BindPoint.of(BindPointParser.DEFINITION,"this is a definition", BindPoint.Type.definition)))
);
}
}