Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support HAL-Forms options #18

Merged
merged 1 commit into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.cosium.hal_mock_mvc;

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;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import java.io.IOException;
import java.util.Map;

/**
* @author Réda Housni Alaoui
*/
class InlineElementRepresentationDeserializer extends StdDeserializer<InlineElementRepresentation> {

public InlineElementRepresentationDeserializer() {
this(null);
}

protected InlineElementRepresentationDeserializer(Class<?> vc) {
super(vc);
}

@Override
public InlineElementRepresentation deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {

JsonToken currentToken = p.currentToken();
if (currentToken == JsonToken.START_OBJECT) {
Map<String, String> map = p.readValueAs(new StringStringMap());
if (map == null) {
return null;
}
return new MapInlineElementRepresentation(map);
}
if (currentToken == JsonToken.VALUE_STRING) {
String value = p.readValueAs(String.class);
if (value == null) {
return null;
}
return new StringInlineElementRepresentation(value);
}

throw MismatchedInputException.from(
p,
InlineElementRepresentation.class,
"%s should have been either %s or %s. But it is not."
.formatted(currentToken, JsonToken.START_OBJECT, JsonToken.VALUE_STRING));
}

private static class StringStringMap extends TypeReference<Map<String, String>> {}
}
26 changes: 26 additions & 0 deletions core/src/main/java/com/cosium/hal_mock_mvc/JacksonModule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.cosium.hal_mock_mvc;

import com.cosium.hal_mock_mvc.template.options.InlineElementRepresentation;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.module.SimpleModule;

/**
* @author Réda Housni Alaoui
*/
class JacksonModule extends SimpleModule {

public JacksonModule() {
addDeserializer(
InlineElementRepresentation.class, new InlineElementRepresentationDeserializer());
}

@Override
public String getModuleName() {
return "com.cosium.hal_mock_mvc";
}

@Override
public Version version() {
return Version.unknownVersion();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static java.util.Objects.requireNonNull;

import com.cosium.hal_mock_mvc.template.options.OptionsRepresentation;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Optional;
Expand All @@ -16,6 +17,7 @@ public class TemplatePropertyRepresentation {
private final String prompt;
private final String regex;
private final boolean templated;
private final OptionsRepresentation options;

@JsonCreator
TemplatePropertyRepresentation(
Expand All @@ -24,13 +26,15 @@ public class TemplatePropertyRepresentation {
@JsonProperty("value") String value,
@JsonProperty("prompt") String prompt,
@JsonProperty("regex") String regex,
@JsonProperty("templated") Boolean templated) {
this.name = requireNonNull(name);
@JsonProperty("templated") Boolean templated,
@JsonProperty("options") OptionsRepresentation options) {
this.name = requireNonNull(name, "Attribute 'name' is missing");
this.required = Optional.ofNullable(required).orElse(false);
this.value = value;
this.prompt = Optional.ofNullable(prompt).orElse(name);
this.regex = regex;
this.templated = Optional.ofNullable(templated).orElse(false);
this.options = options;
}

public String name() {
Expand All @@ -56,4 +60,8 @@ public Optional<String> regex() {
public boolean templated() {
return templated;
}

public Optional<OptionsRepresentation> options() {
return Optional.ofNullable(options);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class TemplateRepresentation {
@JsonProperty("properties") List<TemplatePropertyRepresentation> properties,
@JsonProperty("target") String target) {
this.title = title;
this.method = requireNonNull(method);
this.method = requireNonNull(method, "Attribute 'method' is missing");
this.contentType = Optional.ofNullable(contentType).orElse(MediaType.APPLICATION_JSON_VALUE);
Map<String, TemplatePropertyRepresentation> mutablePropertyByName =
Optional.ofNullable(properties).orElseGet(Collections::emptyList).stream()
Expand Down
1 change: 1 addition & 0 deletions core/src/main/java/com/cosium/hal_mock_mvc/Templates.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class Templates {
body =
new ObjectMapper()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.registerModule(new JacksonModule())
.readValue(jsonBody, HalFormsBody.class);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.cosium.hal_mock_mvc.template.options;

/**
* @author Réda Housni Alaoui
*/
public sealed interface InlineElementRepresentation
permits MapInlineElementRepresentation, StringInlineElementRepresentation {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.cosium.hal_mock_mvc.template.options;

import java.util.Map;
import java.util.Optional;

/**
* @author Réda Housni Alaoui
*/
public record MapInlineElementRepresentation(Map<String, String> map)
implements InlineElementRepresentation {

public MapInlineElementRepresentation(Map<String, String> map) {
this.map = Optional.ofNullable(map).map(Map::copyOf).orElseGet(Map::of);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.cosium.hal_mock_mvc.template.options;

import static java.util.Objects.requireNonNull;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Optional;

/**
* @author Réda Housni Alaoui
*/
public class OptionsLinkRepresentation {

private final String href;
private final String type;
private final boolean templated;

@JsonCreator
public OptionsLinkRepresentation(
@JsonProperty("href") String href,
@JsonProperty("type") String type,
@JsonProperty("templated") Boolean templated) {
this.href = requireNonNull(href, "Attribute 'href' is missing");
this.type = type;
this.templated = Optional.ofNullable(templated).orElse(false);
}

public String href() {
return href;
}

public Optional<String> type() {
return Optional.ofNullable(type);
}

public boolean templated() {
return templated;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.cosium.hal_mock_mvc.template.options;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.Optional;

/**
* @author Réda Housni Alaoui
*/
public class OptionsRepresentation {

private final List<InlineElementRepresentation> inline;
private final OptionsLinkRepresentation link;
private final Long maxItems;
private final long minItems;
private final String promptField;
private final List<String> selectedValues;
private final String valueField;

@JsonCreator
public OptionsRepresentation(
@JsonProperty("inline") List<InlineElementRepresentation> inline,
@JsonProperty("link") OptionsLinkRepresentation link,
@JsonProperty("maxItems") Long maxItems,
@JsonProperty("minItems") Long minItems,
@JsonProperty("promptField") String promptField,
@JsonProperty("selectedValues") List<String> selectedValues,
@JsonProperty("valueField") String valueField) {
this.inline = Optional.ofNullable(inline).map(List::copyOf).orElseGet(List::of);
this.link = link;
this.maxItems = maxItems;
this.minItems = Optional.ofNullable(minItems).orElse(0L);
this.promptField = promptField;
this.selectedValues = Optional.ofNullable(selectedValues).map(List::copyOf).orElseGet(List::of);
this.valueField = valueField;
}

public List<InlineElementRepresentation> inline() {
return inline;
}

public Optional<OptionsLinkRepresentation> link() {
return Optional.ofNullable(link);
}

public Optional<Long> maxItems() {
return Optional.ofNullable(maxItems);
}

public long minItems() {
return minItems;
}

public Optional<String> promptField() {
return Optional.ofNullable(promptField);
}

public List<String> selectedValues() {
return selectedValues;
}

public Optional<String> valueField() {
return Optional.ofNullable(valueField);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.cosium.hal_mock_mvc.template.options;

import static java.util.Objects.requireNonNull;

/**
* @author Réda Housni Alaoui
*/
public record StringInlineElementRepresentation(String value)
implements InlineElementRepresentation {

public StringInlineElementRepresentation {
requireNonNull(value);
}
}
Loading
Loading