change Parameter domain handling

This commit is contained in:
Jörg Prante 2023-03-21 16:39:29 +01:00
parent 1dc1825672
commit c37ff23865
10 changed files with 175 additions and 111 deletions

View file

@ -1,5 +1,5 @@
group = org.xbib
name = net
version = 3.0.3
version = 3.0.4
org.gradle.warning.mode = ALL

View file

@ -21,7 +21,7 @@ public class PathDecoder {
String path = pos > 0 ? pathAndQuery.substring(0, pos) : pathAndQuery;
this.query = pos > 0 ? pathAndQuery.substring(pos + 1) : null;
this.path = PathNormalizer.normalize(path);
this.params = Parameter.builder().enablePercentDeccoding();
this.params = Parameter.builder().enablePercentDecoding();
if (query != null) {
parse(query);
}

View file

@ -11,15 +11,15 @@ class PathDecoderTest {
@Test
void testPlusSign() throws Exception {
PathDecoder decoder = new PathDecoder("/path?a=b+c", "d=e+f");
assertEquals("[b c]", decoder.getParameter().getAll("DEFAULT", "a").toString());
assertEquals("[e f]", decoder.getParameter().getAll("DEFAULT", "d").toString());
assertEquals("[b c]", decoder.getParameter().getAll("a", "DEFAULT").toString());
assertEquals("[e f]", decoder.getParameter().getAll("d", "DEFAULT").toString());
}
@Test
void testSlash() throws Exception {
PathDecoder decoder = new PathDecoder("path/foo/bar/?a=b+c", "d=e+f");
assertEquals("[b c]", decoder.getParameter().getAll("DEFAULT", "a").toString());
assertEquals("[e f]", decoder.getParameter().getAll("DEFAULT", "d").toString());
assertEquals("[b c]", decoder.getParameter().getAll("a", "DEFAULT").toString());
assertEquals("[e f]", decoder.getParameter().getAll("d", "DEFAULT").toString());
}
@Test
@ -32,16 +32,16 @@ class PathDecoderTest {
void testSlashes() throws Exception {
PathDecoder decoder = new PathDecoder("//path?a=b+c", "d=e+f");
assertEquals("/path", decoder.path());
assertEquals("[b c]", decoder.getParameter().getAll("DEFAULT", "a").toString());
assertEquals("[e f]", decoder.getParameter().getAll("DEFAULT", "d").toString());
assertEquals("[b c]", decoder.getParameter().getAll("a", "DEFAULT").toString());
assertEquals("[e f]", decoder.getParameter().getAll("d", "DEFAULT").toString());
}
@Test
void testPlusPercent() throws Exception {
PathDecoder decoder = new PathDecoder("//path?a=b%2Bc", "d=e%2Bf");
assertEquals("/path", decoder.path());
assertEquals("[b+c]", decoder.getParameter().getAll("DEFAULT", "a").toString());
assertEquals("[e+f]", decoder.getParameter().getAll("DEFAULT", "d").toString());
assertEquals("[b+c]", decoder.getParameter().getAll("a", "DEFAULT").toString());
assertEquals("[e+f]", decoder.getParameter().getAll("d", "DEFAULT").toString());
}
@Test
@ -58,7 +58,7 @@ class PathDecoderTest {
}
assertEquals("x-fl-key=20190035592&x-source=ftp://dummy@xbib.org/upload/20190035592/20190035592.pdf&x-fl-target=ftp://dummy@xbib.org/fl/download/20190035592/Fernleihe_Kopienlieferung_null_FB201900373_BLQDMT62_20190035592_20190035592.pdf&x-fl-copy=&x-fl-ack=https://xbib.org/ack/&x-fl-pages=1-", url.getDecodedQuery());
assertEquals("[x-fl-key=20190035592, x-source=ftp://dummy@xbib.org/upload/20190035592/20190035592.pdf, x-fl-target=ftp://dummy@xbib.org/fl/download/20190035592/Fernleihe_Kopienlieferung_null_FB201900373_BLQDMT62_20190035592_20190035592.pdf, x-fl-copy=, x-fl-ack=https://xbib.org/ack/, x-fl-pages=1-]", decoder.getParameter().toString());
url = URL.from(decoder.getParameter().getAll("DEFAULT", "x-fl-target").get(0).toString());
url = URL.from(decoder.getParameter().getAll("x-fl-target", "DEFAULT").get(0).toString());
assertEquals("ftp://dummy@xbib.org/fl/download/20190035592/Fernleihe_Kopienlieferung_null_FB201900373_BLQDMT62_20190035592_20190035592.pdf", url.toString());
}
}

View file

@ -314,13 +314,13 @@ class PathMatcherTest {
void extractUriTemplateVariablesRegex() {
Parameter result = pathMatcher.extractUriTemplateVariables("{symbolicName:[\\w\\.]+}-{version:[\\w\\.]+}.jar",
"com.example-1.0.0.jar");
assertEquals("com.example", result.getAll("DEFAULT", "symbolicName").get(0));
assertEquals("1.0.0", result.getAll("DEFAULT", "version").get(0));
assertEquals("com.example", result.getAll("symbolicName", "DEFAULT").get(0));
assertEquals("1.0.0", result.getAll("version", "DEFAULT").get(0));
result = pathMatcher.extractUriTemplateVariables("{symbolicName:[\\w\\.]+}-sources-{version:[\\w\\.]+}.jar",
"com.example-sources-1.0.0.jar");
assertEquals("com.example", result.getAll("DEFAULT", "symbolicName").get(0));
assertEquals("1.0.0", result.getAll("DEFAULT", "version").get(0));
assertEquals("com.example", result.getAll("symbolicName", "DEFAULT").get(0));
assertEquals("1.0.0", result.getAll("version", "DEFAULT").get(0));
}
@Test
@ -328,21 +328,21 @@ class PathMatcherTest {
Parameter result = pathMatcher.extractUriTemplateVariables(
"{symbolicName:[\\p{L}\\.]+}-sources-{version:[\\p{N}\\.]+}.jar",
"com.example-sources-1.0.0.jar");
assertEquals("com.example", result.getAll("DEFAULT", "symbolicName").get(0));
assertEquals("1.0.0", result.getAll("DEFAULT", "version").get(0));
assertEquals("com.example", result.getAll("symbolicName", "DEFAULT").get(0));
assertEquals("1.0.0", result.getAll("version", "DEFAULT").get(0));
result = pathMatcher.extractUriTemplateVariables(
"{symbolicName:[\\w\\.]+}-sources-{version:[\\d\\.]+}-{year:\\d{4}}{month:\\d{2}}{day:\\d{2}}.jar",
"com.example-sources-1.0.0-20100220.jar");
assertEquals("com.example", result.getAll("DEFAULT", "symbolicName").get(0));
assertEquals("1.0.0", result.getAll("DEFAULT", "version").get(0));
assertEquals("2010", result.getAll("DEFAULT", "year").get(0));
assertEquals("02", result.getAll("DEFAULT", "month").get(0));
assertEquals("20", result.getAll("DEFAULT", "day").get(0));
assertEquals("com.example", result.getAll("symbolicName", "DEFAULT").get(0));
assertEquals("1.0.0", result.getAll("version", "DEFAULT").get(0));
assertEquals("2010", result.getAll("year", "DEFAULT").get(0));
assertEquals("02", result.getAll("month", "DEFAULT").get(0));
assertEquals("20", result.getAll("day", "DEFAULT").get(0));
result = pathMatcher.extractUriTemplateVariables(
"{symbolicName:[\\p{L}\\.]+}-sources-{version:[\\p{N}\\.\\{\\}]+}.jar",
"com.example-sources-1.0.0.{12}.jar");
assertEquals("com.example", result.getAll("DEFAULT", "symbolicName").get(0));
assertEquals("1.0.0.{12}", result.getAll("DEFAULT", "version").get(0));
assertEquals("com.example", result.getAll("symbolicName", "DEFAULT").get(0));
assertEquals("1.0.0.{12}", result.getAll("version", "DEFAULT").get(0));
}
@Test

View file

@ -147,12 +147,12 @@ class PathResolverTest {
.add("GET", "test/{two}", 4321)
.build();
pathResolver.resolve("GET", "test/foo", result -> {
if (result.getParameter().containsKey("PATH", "one")) {
if (result.getParameter().containsKey("one", "PATH")) {
assertThat(result.getValue(), is(1234));
assertThat(result.getParameter().get("PATH", "one"), is("foo"));
assertThat(result.getParameter().get("one", "PATH"), is("foo"));
} else {
assertThat(result.getValue(), is(4321));
assertThat(result.getParameter().get("PATH", "two"), is("foo"));
assertThat(result.getParameter().get("two", "PATH"), is("foo"));
}
});
}

View file

@ -14,7 +14,6 @@ import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@ -116,7 +115,7 @@ class PathResolverTest {
.build();
pathResolver.resolve("GET", "one/two/three/four", result -> {
assertThat(result.getValue(), anyOf(equalTo(1234), equalTo(4321)));
if (result.getParameter().containsKey("PATH", "three")) {
if (result.getParameter().containsKey("three", "PATH")) {
assertThat(result.getParameter(), is(Parameter.of("PATH", Map.of("three", "three"))));
} else {
assertThat(result.getParameter(), is(Parameter.of("PATH", Map.of("one", "one", "two", "two", "four", "four"))));
@ -231,7 +230,7 @@ class PathResolverTest {
}
private void assertSuccessfulResolution(PathResolver<Integer> pathResolver, String path, Integer value) {
assertSuccessfulResolution(pathResolver, "GET", path, value, Parameter.of("PATH"));
assertSuccessfulResolution(pathResolver, "GET", path, value, Parameter.builder().domain("PATH").build());
}
private void assertSuccessfulResolution(PathResolver<Integer> pathResolver, String method, String path, Integer value,

View file

@ -1,5 +1,6 @@
package org.xbib.net;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
@ -7,6 +8,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.xbib.datastructures.common.ImmutableList;
@ -44,10 +46,6 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
return EMPTY;
}
public static Parameter of(String domain) {
return Parameter.builder().domain(domain).build();
}
public static Parameter of(Map<String, Object> map) {
return Parameter.builder().enableSort().add(map).build();
}
@ -75,31 +73,46 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
@Override
public int compareTo(Parameter o) {
return toString().compareTo(o.toString());
return list.toString().compareTo(o.list.toString());
}
@Override
public String toString() {
return list.toString();
return allToString();
}
public String getDomain() {
return builder.domain;
}
@SuppressWarnings("unchecked")
public String getAsString(String domain, String key) {
Object object = get(domain, key);
public String getAsString(String key, String... domains) {
Object object = get(key, domains);
if (object instanceof Collection) {
Collection<Object> collection = (Collection<Object>) object;
object = collection.iterator().next();
Iterator<Object> iterator = collection.iterator();
if (iterator.hasNext()) {
object = iterator.next();
} else {
object = null;
}
return object != null ? object.toString() : null;
}
return object != null ? object instanceof String ? (String) object : object.toString() : null;
}
@SuppressWarnings("unchecked")
public Integer getAsInteger(String domain, String key) {
Object object = get(domain, key);
public Integer getAsInteger(String key, String... domains) {
Object object = get(key, domains);
if (object instanceof Collection) {
Collection<Object> collection = (Collection<Object>) object;
object = collection.iterator().next();
Iterator<Object> iterator = collection.iterator();
if (iterator.hasNext()) {
object = iterator.next();
} else {
object = null;
}
return object != null ? Integer.parseInt(object.toString()) : null;
}
try {
@ -110,11 +123,16 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
}
@SuppressWarnings("unchecked")
public Boolean getAsBoolean(String domain, String key) {
Object object = get(domain, key);
public Boolean getAsBoolean(String key, String... domains) {
Object object = get(key, domains);
if (object instanceof Collection) {
Collection<Object> collection = (Collection<Object>) object;
object = collection.iterator().next();
Iterator<Object> iterator = collection.iterator();
if (iterator.hasNext()) {
object = iterator.next();
} else {
object = null;
}
return object != null ? Boolean.parseBoolean(object.toString()) : null;
}
try {
@ -127,9 +145,7 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
public String allToString() {
StringBuilder sb = new StringBuilder();
sb.append(list.toString());
if (!builder.parameterMap.isEmpty()) {
builder.parameterMap.forEach((key, value) -> sb.append(" ").append(key).append(" -> ").append(value));
}
builder.parameterMap.forEach((key, value) -> sb.append(" ").append(key).append(" -> ").append(value));
return sb.toString();
}
@ -162,57 +178,102 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
return object;
}
public String getDomain() {
return builder.domain;
}
public Stream<Pair<String, Object>> stream(String domain) {
if (!builder.domain.equals(domain)) {
throw new IllegalArgumentException("domain mismatch");
}
return list.stream();
}
public List<Object> getAll(String domain, String key) {
Optional<Parameter> optional = builder.parameterMap.values().stream().filter(p -> domain.equals(p.getDomain())).findFirst();
if (optional.isPresent()) {
return optional.get().getAll(domain, key);
} else {
if (!builder.domain.equals(domain)) {
throw new IllegalArgumentException("domain mismatch");
public List<Object> getAllDomain(String... domains) {
Parameter parameter = null;
for (String domain : domains) {
if (builder.parameterMap.containsKey(domain)) {
parameter = builder.parameterMap.get(domain);
}
if (parameter != null) {
List<Object> list = parameter.getAllDomain(domains);
if (list != null) {
return list;
}
}
return list.stream()
.filter(p -> key.equals(p.getKey()))
.map(Pair::getValue)
.collect(Collectors.toList());
}
return null;
}
public boolean containsKey(String domain, String key) {
Optional<Parameter> optional = builder.parameterMap.values().stream().filter(p -> domain.equals(p.getDomain())).findFirst();
if (optional.isPresent()) {
return optional.get().containsKey(domain, key);
} else {
if (!builder.domain.equals(domain)) {
throw new IllegalArgumentException("domain mismatch");
public boolean isPresent(String... domains) {
Parameter parameter = null;
for (String domain : domains) {
if (builder.parameterMap.containsKey(domain)) {
parameter = builder.parameterMap.get(domain);
}
return list.stream().anyMatch(p -> key.equals(p.getKey()));
if (parameter != null) {
boolean b = parameter.isPresent(domains);
if (b) {
return true;
}
}
return list.stream().findAny().isPresent();
}
return false;
}
public Object get(String domain, String key) {
Optional<Parameter> optional = builder.parameterMap.values().stream().filter(p -> domain.equals(p.getDomain())).findFirst();
if (optional.isPresent()) {
return optional.get().getAll(domain, key);
} else {
if (!builder.domain.equals(domain)) {
throw new IllegalArgumentException("domain mismatch");
public List<Object> getAll(String key, String... domains) {
Parameter parameter = null;
for (String domain : domains) {
if (builder.parameterMap.containsKey(domain)) {
parameter = builder.parameterMap.get(domain);
}
if (parameter != null) {
List<Object> list = parameter.getAll(key, domains);
if (list != null) {
return list;
}
}
return list.stream()
.filter(p -> key.equals(p.getKey()))
.filter(p -> p.getKey().equals(key))
.map(Pair::getValue)
.findFirst().orElse(null);
.collect(Collectors.toList());
}
return null;
}
public boolean containsKey(String key, String... domains) {
Parameter parameter = null;
for (String domain : domains) {
if (builder.parameterMap.containsKey(domain)) {
parameter = builder.parameterMap.get(domain);
}
if (parameter != null) {
boolean b = parameter.containsKey(key, domains);
if (b) {
return true;
}
}
return list.stream()
.anyMatch(p -> key.equals(p.getKey()));
}
return false;
}
public Object get(String key, String... domains) {
Parameter parameter = null;
for (String domain : domains) {
if (builder.parameterMap.containsKey(domain)) {
parameter = builder.parameterMap.get(domain);
}
if (parameter != null) {
Object object = parameter.get(key, domains);
if (object != null) {
return object;
}
} else {
Optional<Object> optional = list.stream()
.filter(p -> key.equals(p.getKey()))
.map(Pair::getValue)
.findFirst();
if (optional.isPresent()) {
return optional.get();
}
}
}
return null;
}
public String getAsQueryString() {

View file

@ -32,7 +32,7 @@ public class ParameterBuilder implements PairValidator {
private final List<Pair<String, Object>> list;
String domain;
protected String domain;
final Map<String, Parameter> parameterMap;
@ -118,7 +118,7 @@ public class ParameterBuilder implements PairValidator {
return this;
}
public ParameterBuilder enablePercentDeccoding() {
public ParameterBuilder enablePercentDecoding() {
this.enablePercentDecoding = true;
charset(StandardCharsets.UTF_8);
return this;
@ -172,11 +172,10 @@ public class ParameterBuilder implements PairValidator {
}
public ParameterBuilder add(Parameter parameter) {
if (domain.equals(parameter.getDomain())) {
parameter.stream(domain).forEach(this::add);
} else {
parameterMap.putIfAbsent(parameter.getDomain(), parameter);
if (parameterMap.containsKey(parameter.getDomain())) {
throw new IllegalArgumentException("unable to add domain " + parameter.getDomain());
}
parameterMap.putIfAbsent(parameter.getDomain(), parameter);
return this;
}

View file

@ -17,8 +17,7 @@ public class ParameterTest {
public void testEmptyBuilder() {
Parameter parameter = Parameter.builder().build();
assertNotNull(parameter);
assertEquals("DEFAULT", parameter.getDomain());
assertFalse(parameter.containsKey("DEFAULT", "param1"));
assertFalse(parameter.containsKey("param1", "DEFAULT"));
}
@Test
@ -27,8 +26,7 @@ public class ParameterTest {
.add("Hello", "World")
.build();
assertNotNull(parameter);
assertEquals("DEFAULT", parameter.getDomain());
assertTrue(parameter.containsKey("DEFAULT", "Hello"));
assertTrue(parameter.containsKey("Hello", "DEFAULT"));
}
@Test
@ -40,9 +38,8 @@ public class ParameterTest {
.add("Hello", "World")
.build();
assertNotNull(parameter);
assertEquals("DEFAULT", parameter.getDomain());
assertTrue(parameter.containsKey("DEFAULT", "Hello"));
assertEquals(List.of("World", "World", "World"), parameter.getAll("DEFAULT", "Hello"));
assertTrue(parameter.containsKey("Hello", "DEFAULT"));
assertEquals(List.of("World", "World", "World"), parameter.getAll("Hello", "DEFAULT"));
}
@Test
@ -57,8 +54,8 @@ public class ParameterTest {
.build();
assertNotNull(parameter);
assertEquals("HEADER", parameter.getDomain());
assertTrue(parameter.containsKey("HEADER", "content-type"));
assertEquals(List.of("close"), parameter.getAll("HEADER", "connection"));
assertTrue(parameter.containsKey("content-type", "HEADER"));
assertEquals(List.of("close"), parameter.getAll( "connection", "HEADER"));
}
@Test
@ -112,7 +109,7 @@ public class ParameterTest {
.build();
URLBuilder mutator = url.mutator();
mutator.path(requestPath);
httpParameter.stream("DEFAULT").forEach(e -> mutator.queryParam(e.getKey(), e.getValue()));
httpParameter.forEach(e -> mutator.queryParam(e.getKey(), e.getValue()));
url = mutator.build();
assertEquals("http://localhost/path?operation=searchRetrieve&query=iss%20%3D%2000280836&recordSchema=MARC21plus-1-xml&version=1.1",
url.toExternalForm());
@ -124,9 +121,9 @@ public class ParameterTest {
String body = "a=b&c=d&e=f";
queryParameters.addPercentEncodedBody(body);
Parameter parameter = queryParameters.build();
assertEquals("b", parameter.getAll("DEFAULT", "a").get(0));
assertEquals("d", parameter.getAll("DEFAULT", "c").get(0));
assertEquals("f", parameter.getAll("DEFAULT", "e").get(0));
assertEquals("b", parameter.getAll("a", "DEFAULT").get(0));
assertEquals("d", parameter.getAll("c", "DEFAULT").get(0));
assertEquals("f", parameter.getAll("e", "DEFAULT").get(0));
}
@Test
@ -140,14 +137,14 @@ public class ParameterTest {
String body = String.join("&", list);
queryParameters.addPercentEncodedBody(body);
Parameter parameter = queryParameters.build();
assertEquals("b0", parameter.getAll("DEFAULT", "a0").get(0));
assertEquals("b99", parameter.getAll("DEFAULT", "a99").get(0));
assertEquals("[]", parameter.getAll("DEFAULT", "a100").toString());
assertEquals("b0", parameter.getAll("a0", "DEFAULT").get(0));
assertEquals("b99", parameter.getAll("a99", "DEFAULT").get(0));
assertEquals("[]", parameter.getAll("a100", "DEFAULT").toString());
});
}
@Test
void testSubDomains() {
void testDomains() {
Parameter p1 = Parameter.builder().domain("A").add("a", "a").build();
Parameter p2 = Parameter.builder().domain("B").add("b", "b").build();
Parameter p3 = Parameter.builder().domain("C").add("c", "c").build();
@ -156,8 +153,16 @@ public class ParameterTest {
.add(p2)
.add(p3)
.build();
assertEquals("[a]", p.get("A", "a").toString());
assertEquals("[b]", p.get("B", "b").toString());
assertEquals("[c]", p.get("C", "c").toString());
assertEquals("a", p.get("a", "A").toString());
assertEquals("b", p.get("b", "B").toString());
assertEquals("c", p.get("c", "C").toString());
assertEquals("[] A -> [a=a] B -> [b=b] C -> [c=c]", p.toString());
assertEquals("a", p.get("a", "A", "B", "C"));
assertEquals("b", p.get("b", "A", "B", "C"));
assertEquals("c", p.get("c", "A", "B", "C"));
assertTrue(p.isPresent("A"));
assertTrue(p.isPresent("B"));
assertTrue(p.isPresent("C"));
assertFalse(p.isPresent("D"));
}
}

View file

@ -327,7 +327,7 @@ class URLParserTest {
assertEquals("path", pathSegment.getSegment());
assertEquals("p2", pathSegment.getMatrixParams().get(0).getKey());
assertEquals("v2", pathSegment.getMatrixParams().get(0).getValue());
assertEquals("v3", url.getQueryParams().getAll("DEFAULT", "q1").get(0));
assertEquals("v3", url.getQueryParams().getAll("q1", "DEFAULT").get(0));
}
@Test