Skip to content

Commit

Permalink
Fixes #2343
Browse files Browse the repository at this point in the history
  • Loading branch information
George Postelnicu committed Jul 17, 2021
1 parent 703f078 commit 02d2ffa
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,37 @@
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static java.lang.String.format;

@API(status = API.Status.STABLE)
public final class DocStringTypeRegistry {

private final Map<String, DocStringType> docStringTypesByContentType = new HashMap<>();
private final Map<Type, DocStringType> docStringTypesByType = new HashMap<>();
private static final Class<String> DEFAULT_TYPE = String.class;
private static final String DEFAULT_CONTENT_TYPE = "";
private final Map<String, Map<Type, DocStringType>> docStringTypes = new HashMap<>();

public DocStringTypeRegistry() {
defineDocStringType(new DocStringType(String.class, "", (String docString) -> docString));
defineDocStringType(new DocStringType(DEFAULT_TYPE, DEFAULT_CONTENT_TYPE, (String docString) -> docString));
}

public void defineDocStringType(DocStringType docStringType) {
DocStringType byContentType = docStringTypesByContentType.get(docStringType.getContentType());
if (byContentType != null) {
throw createDuplicateTypeException(byContentType, docStringType);
if (docStringTypes.containsKey(docStringType.getContentType()) &&
docStringTypes.get(docStringType.getContentType()).containsKey(docStringType.getType())) {
throw createDuplicateTypeException(
docStringTypes.get(docStringType.getContentType()).get(docStringType.getType()),
docStringType);
}
DocStringType byClass = docStringTypesByType.get(docStringType.getType());
if (byClass != null) {
throw createDuplicateTypeException(byClass, docStringType);

Map<Type, DocStringType> map;
if (docStringTypes.containsKey(docStringType.getContentType())) {
map = docStringTypes.get(docStringType.getContentType());
} else {
map = new HashMap<>();
}
docStringTypesByContentType.put(docStringType.getContentType(), docStringType);
docStringTypesByType.put(docStringType.getType(), docStringType);
map.put(docStringType.getType(), docStringType);
docStringTypes.put(docStringType.getContentType(), map);
}

private static CucumberDocStringException createDuplicateTypeException(
Expand All @@ -49,12 +55,16 @@ private static String emptyToAnonymous(String contentType) {
return contentType.isEmpty() ? "[anonymous]" : contentType;
}

DocStringType lookupByContentType(String contentType) {
return docStringTypesByContentType.get(contentType);
}

DocStringType lookupByType(Type type) {
return docStringTypesByType.get(type);
Optional<DocStringType> lookup(String contentType, Type type) {
if (Objects.isNull(contentType)) {
if (docStringTypes.get(DEFAULT_CONTENT_TYPE).containsKey(type)) {
return Optional.of(docStringTypes.get(DEFAULT_CONTENT_TYPE).get(type));
}
}
if (docStringTypes.containsKey(contentType) &&
docStringTypes.get(contentType).containsKey(type)) {
return Optional.of(docStringTypes.get(contentType).get(type));
}
return Optional.empty();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.apiguardian.api.API;

import java.lang.reflect.Type;
import java.util.Optional;

import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
Expand All @@ -23,14 +24,9 @@ public <T> T convert(DocString docString, Type targetType) {
return (T) docString;
}

DocStringType docStringType = docStringTypeRegistry.lookupByContentType(docString.getContentType());
if (docStringType != null) {
return (T) docStringType.transform(docString.getContent());
}

docStringType = docStringTypeRegistry.lookupByType(targetType);
if (docStringType != null) {
return (T) docStringType.transform(docString.getContent());
Optional<DocStringType> lookup = docStringTypeRegistry.lookup(docString.getContentType(), targetType);
if (lookup.isPresent()) {
return (T) lookup.get().transform(docString.getContent());
}

if (docString.getContentType() == null) {
Expand Down
11 changes: 0 additions & 11 deletions docstring/src/test/java/io/cucumber/docstring/DocStringTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,9 @@

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

class DocStringTest {

@Test
void throws_when_no_converter_defined() {
DocString docString = DocString.create("hello world");
CucumberDocStringException exception = assertThrows(
CucumberDocStringException.class,
() -> docString.convert(Object.class));
assertThat(exception.getMessage(), is("" +
"Can't convert DocString to class java.lang.Object. You have to write the conversion for it in this method"));
}

@Test
void pretty_prints_doc_string_objects() {
DocString docString = DocString.create(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,11 @@ class DocStringTypeRegistryDocStringConverterTest {
private final DocStringTypeRegistryDocStringConverter converter = new DocStringTypeRegistryDocStringConverter(
registry);

@Test
void uses_doc_string_type_when_available() {
registry.defineDocStringType(new DocStringType(
JsonNode.class,
"json",
(String s) -> new ObjectMapper().readTree(s)));

DocString docString = DocString.create(
"{\"hello\":\"world\"}",
"json");

JsonNode converted = converter.convert(docString, Object.class);
assertThat(converted.get("hello").textValue(), is("world"));
}

@Test
void uses_target_type_when_available() {
registry.defineDocStringType(new DocStringType(
JsonNode.class,
"json",
(String s) -> new ObjectMapper().readTree(s)));

DocString docString = DocString.create(
"{\"hello\":\"world\"}");

JsonNode converted = converter.convert(docString, JsonNode.class);
assertThat(converted.get("hello").textValue(), is("world"));
}

@Test
void target_type_to_string_is_predefined() {
DocString docString = DocString.create(
"hello world");

String converted = converter.convert(docString, String.class);
assertThat(converted, is("hello world"));
}
Expand All @@ -61,6 +33,18 @@ void converts_doc_string_to_doc_string() {
assertThat(converted, is(docString));
}

@Test
void throws_when_no_converter_defined() {
DocString docString = DocString.create("hello world");

CucumberDocStringException exception = assertThrows(
CucumberDocStringException.class,
() -> docString.convert(Object.class));

assertThat(exception.getMessage(), is("" +
"Can't convert DocString to class java.lang.Object. You have to write the conversion for it in this method"));
}

@Test
void throws_when_no_converter_available() {
DocString docString = DocString.create(
Expand Down Expand Up @@ -112,4 +96,23 @@ void throws_when_conversion_fails() {
" \"\"\"")));
}

@Test
void throws_when_uses_doc_string_type_but_downcast_conversion() {
registry.defineDocStringType(new DocStringType(
JsonNode.class,
"json",
(String s) -> new ObjectMapper().readTree(s)));

DocString docString = DocString.create(
"{\"hello\":\"world\"}",
"json");

CucumberDocStringException exception = assertThrows(
CucumberDocStringException.class,
() -> converter.convert(docString, Object.class));

assertThat(exception.getMessage(), is("" +
"It appears you did not register docstring type for 'json' or java.lang.Object"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ void anonymous_doc_string_is_predefined() {
}

@Test
void doc_string_types_must_be_unique() {
void doc_string_types_of_same_content_type_must_be_unique() {
registry.defineDocStringType(new DocStringType(
JsonNode.class,
"json",
"application/json",
(String s) -> null));

DocStringType duplicate = new DocStringType(
Expand All @@ -42,7 +42,8 @@ void doc_string_types_must_be_unique() {
CucumberDocStringException.class,
() -> registry.defineDocStringType(duplicate));
assertThat(exception.getMessage(), is("" +
"There is already docstring type registered for 'json' and com.fasterxml.jackson.databind.JsonNode.\n" +
"There is already docstring type registered for 'application/json' and com.fasterxml.jackson.databind.JsonNode.\n"
+
"You are trying to add 'application/json' and com.fasterxml.jackson.databind.JsonNode"));
}

Expand Down

0 comments on commit 02d2ffa

Please sign in to comment.