-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
34c8ba3
commit 4a032d9
Showing
10 changed files
with
329 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package com.cosium.hal_mock_mvc; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
|
||
/** | ||
* @author Réda Housni Alaoui | ||
*/ | ||
public class Form { | ||
|
||
private final RequestExecutor requestExecutor; | ||
private final ObjectMapper objectMapper; | ||
private final Template template; | ||
|
||
private final Map<String, FormProperty<?>> propertyByName = new HashMap<>(); | ||
|
||
Form(RequestExecutor requestExecutor, ObjectMapper objectMapper, Template template) { | ||
this.requestExecutor = requireNonNull(requestExecutor); | ||
this.objectMapper = requireNonNull(objectMapper); | ||
this.template = requireNonNull(template); | ||
} | ||
|
||
public Form withStringValue(String propertyName, String value) throws Exception { | ||
FormProperty<?> property = | ||
new FormProperty<>(String.class, propertyName, List.of(value), false); | ||
propertyByName.put(property.name(), assertValid(property)); | ||
return this; | ||
} | ||
|
||
public Form withBooleanValue(String propertyName, Boolean value) throws Exception { | ||
FormProperty<?> property = | ||
new FormProperty<>(Boolean.class, propertyName, List.of(value), false); | ||
propertyByName.put(property.name(), assertValid(property)); | ||
return this; | ||
} | ||
|
||
public Form withIntegerValue(String propertyName, Integer value) throws Exception { | ||
FormProperty<?> property = | ||
new FormProperty<>(Integer.class, propertyName, List.of(value), false); | ||
propertyByName.put(property.name(), assertValid(property)); | ||
return this; | ||
} | ||
|
||
public Form withLongValue(String propertyName, Long value) throws Exception { | ||
FormProperty<?> property = new FormProperty<>(Long.class, propertyName, List.of(value), false); | ||
propertyByName.put(property.name(), assertValid(property)); | ||
return this; | ||
} | ||
|
||
public Form withDoubleValue(String propertyName, Double value) throws Exception { | ||
FormProperty<?> property = | ||
new FormProperty<>(Double.class, propertyName, List.of(value), false); | ||
propertyByName.put(property.name(), assertValid(property)); | ||
return this; | ||
} | ||
|
||
public Form withStringValues(String propertyName, List<String> value) throws Exception { | ||
FormProperty<?> property = new FormProperty<>(String.class, propertyName, value, true); | ||
propertyByName.put(property.name(), assertValid(property)); | ||
return this; | ||
} | ||
|
||
public Form withBooleanValues(String propertyName, List<Boolean> value) throws Exception { | ||
FormProperty<?> property = new FormProperty<>(Boolean.class, propertyName, value, true); | ||
propertyByName.put(property.name(), assertValid(property)); | ||
return this; | ||
} | ||
|
||
public Form withIntValues(String propertyName, List<Integer> value) throws Exception { | ||
FormProperty<?> property = new FormProperty<>(Integer.class, propertyName, value, true); | ||
propertyByName.put(property.name(), assertValid(property)); | ||
return this; | ||
} | ||
|
||
public Form withLongValues(String propertyName, List<Long> value) throws Exception { | ||
FormProperty<?> property = new FormProperty<>(Long.class, propertyName, value, true); | ||
propertyByName.put(property.name(), assertValid(property)); | ||
return this; | ||
} | ||
|
||
public Form withDoubleValues(String propertyName, List<Double> value) throws Exception { | ||
FormProperty<?> property = new FormProperty<>(Double.class, propertyName, value, true); | ||
propertyByName.put(property.name(), assertValid(property)); | ||
return this; | ||
} | ||
|
||
private FormProperty<?> assertValid(FormProperty<?> property) throws Exception { | ||
return new TemplateProperty(requestExecutor, objectMapper, requireTemplate(property)) | ||
.assertValid(property); | ||
} | ||
|
||
private TemplatePropertyRepresentation requireTemplate(FormProperty<?> property) { | ||
return Optional.ofNullable(template.representation().propertyByName().get(property.name())) | ||
.orElseThrow( | ||
() -> | ||
new IllegalArgumentException( | ||
"No property found for name '%s'".formatted(property.name()))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.cosium.hal_mock_mvc; | ||
|
||
import java.util.List; | ||
|
||
/** | ||
* @author Réda Housni Alaoui | ||
*/ | ||
record FormProperty<T>(Class<T> valueType, String name, List<T> values, boolean array) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
core/src/main/java/com/cosium/hal_mock_mvc/TemplateOptions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package com.cosium.hal_mock_mvc; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
|
||
import com.cosium.hal_mock_mvc.template.options.InlineElementRepresentation; | ||
import com.cosium.hal_mock_mvc.template.options.OptionsLinkRepresentation; | ||
import com.cosium.hal_mock_mvc.template.options.OptionsRepresentation; | ||
import com.fasterxml.jackson.core.type.TypeReference; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import java.util.List; | ||
import org.springframework.hateoas.Link; | ||
|
||
/** | ||
* @author Réda Housni Alaoui | ||
*/ | ||
class TemplateOptions { | ||
|
||
private final RequestExecutor requestExecutor; | ||
private final ObjectMapper objectMapper; | ||
private final OptionsRepresentation representation; | ||
|
||
TemplateOptions( | ||
RequestExecutor requestExecutor, | ||
ObjectMapper objectMapper, | ||
OptionsRepresentation representation) { | ||
this.requestExecutor = requireNonNull(requestExecutor); | ||
this.objectMapper = requireNonNull(objectMapper); | ||
this.representation = requireNonNull(representation); | ||
} | ||
|
||
public FormProperty<?> assertValid(FormProperty<?> property) throws Exception { | ||
if (!String.class.equals(property.valueType())) { | ||
throw new IllegalArgumentException( | ||
"Cannot set a value of type '%s' because property '%s' expects a value from an enumeration of options." | ||
.formatted(property.valueType(), property.name())); | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
FormProperty<String> stringProperty = (FormProperty<String>) property; | ||
|
||
String valueField = representation.valueField().orElse("value"); | ||
|
||
List<InlineElementRepresentation> inlineElements = representation.inline().orElse(null); | ||
if (inlineElements != null) { | ||
return new TemplateOptionsInlineElements(valueField, inlineElements) | ||
.assertValuesAreValidOptions(stringProperty); | ||
} | ||
|
||
OptionsLinkRepresentation optionsLink = representation.link().orElse(null); | ||
if (optionsLink == null) { | ||
throw new IllegalArgumentException( | ||
"Missing inline and remote elements from options %s.".formatted(representation)); | ||
} | ||
|
||
return new TemplateOptionsInlineElements(valueField, fetchRemoteElements(optionsLink)) | ||
.assertValuesAreValidOptions(stringProperty); | ||
} | ||
|
||
private List<InlineElementRepresentation> fetchRemoteElements( | ||
OptionsLinkRepresentation optionsLink) throws Exception { | ||
|
||
String optionsHref = Link.of(optionsLink.href()).expand().toUri().toString(); | ||
|
||
String rawOptions = | ||
requestExecutor | ||
.execute(get(optionsHref)) | ||
.andExpect(status().is2xxSuccessful()) | ||
.andReturn() | ||
.getResponse() | ||
.getContentAsString(); | ||
|
||
return objectMapper.readValue(rawOptions, new TypeReference<>() {}); | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
core/src/main/java/com/cosium/hal_mock_mvc/TemplateOptionsInlineElement.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.cosium.hal_mock_mvc; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
import com.cosium.hal_mock_mvc.template.options.InlineElementRepresentation; | ||
import com.cosium.hal_mock_mvc.template.options.MapInlineElementRepresentation; | ||
import com.cosium.hal_mock_mvc.template.options.StringInlineElementRepresentation; | ||
|
||
/** | ||
* @author Réda Housni Alaoui | ||
*/ | ||
class TemplateOptionsInlineElement { | ||
|
||
private final String valueField; | ||
private final InlineElementRepresentation representation; | ||
|
||
TemplateOptionsInlineElement(String valueField, InlineElementRepresentation representation) { | ||
this.valueField = requireNonNull(valueField); | ||
this.representation = requireNonNull(representation); | ||
} | ||
|
||
public boolean matches(String value) { | ||
if (representation instanceof MapInlineElementRepresentation mapInlineElementRepresentation) { | ||
|
||
return value.equals(mapInlineElementRepresentation.map().get(valueField)); | ||
|
||
} else if (representation | ||
instanceof StringInlineElementRepresentation stringInlineElementRepresentation) { | ||
|
||
return value.equals(stringInlineElementRepresentation.value()); | ||
|
||
} else { | ||
throw new IllegalArgumentException("Unexpected type %s".formatted(representation.getClass())); | ||
} | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
core/src/main/java/com/cosium/hal_mock_mvc/TemplateOptionsInlineElements.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package com.cosium.hal_mock_mvc; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
import com.cosium.hal_mock_mvc.template.options.InlineElementRepresentation; | ||
import java.util.List; | ||
|
||
/** | ||
* @author Réda Housni Alaoui | ||
*/ | ||
class TemplateOptionsInlineElements { | ||
private final String valueField; | ||
private final List<InlineElementRepresentation> representations; | ||
|
||
TemplateOptionsInlineElements( | ||
String valueField, List<InlineElementRepresentation> representations) { | ||
this.valueField = requireNonNull(valueField); | ||
this.representations = List.copyOf(representations); | ||
} | ||
|
||
public FormProperty<String> assertValuesAreValidOptions(FormProperty<String> property) { | ||
|
||
if (representations.isEmpty()) { | ||
throw new IllegalArgumentException( | ||
"Value of property '%s' cannot be non null because the list of available option is empty." | ||
.formatted(property.name())); | ||
} | ||
|
||
List<TemplateOptionsInlineElement> inlineElements = | ||
representations.stream() | ||
.map(representation -> new TemplateOptionsInlineElement(valueField, representation)) | ||
.toList(); | ||
|
||
for (String value : property.values()) { | ||
|
||
if (inlineElements.stream().anyMatch(inlineElement -> inlineElement.matches(value))) { | ||
continue; | ||
} | ||
|
||
throw new IllegalArgumentException( | ||
"Value '%s' didn't match any inline option of property '%s' among %s" | ||
.formatted(value, property.name(), representations)); | ||
} | ||
|
||
return property; | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
core/src/main/java/com/cosium/hal_mock_mvc/TemplateProperty.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.cosium.hal_mock_mvc; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
import com.cosium.hal_mock_mvc.template.options.OptionsRepresentation; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
|
||
/** | ||
* @author Réda Housni Alaoui | ||
*/ | ||
class TemplateProperty { | ||
|
||
private final RequestExecutor requestExecutor; | ||
private final ObjectMapper objectMapper; | ||
private final TemplatePropertyRepresentation representation; | ||
|
||
TemplateProperty( | ||
RequestExecutor requestExecutor, | ||
ObjectMapper objectMapper, | ||
TemplatePropertyRepresentation representation) { | ||
this.requestExecutor = requireNonNull(requestExecutor); | ||
this.objectMapper = requireNonNull(objectMapper); | ||
this.representation = requireNonNull(representation); | ||
} | ||
|
||
public FormProperty<?> assertValid(FormProperty<?> property) throws Exception { | ||
OptionsRepresentation options = representation.options().orElse(null); | ||
if (options != null) { | ||
return new TemplateOptions(requestExecutor, objectMapper, options).assertValid(property); | ||
} | ||
return property; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.