Skip to content

Provide a property creation context to HalFormsOptionsFactory #2275

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
26 changes: 24 additions & 2 deletions src/main/java/org/springframework/hateoas/AffordanceModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,35 @@ public PayloadMetadata getOutput() {
* @return will never be {@literal null}.
* @since 1.3
*/
public <T> List<T> createProperties(BiFunction<InputPayloadMetadata, PropertyMetadata, T> creator) {
public <T> List<T> createProperties(PropertyCreator<T> creator) {

PropertyCreationContext context = new PropertyCreationContext(getLink());
return input.stream() //
.map(it -> creator.apply(input, it)) //
.map(it -> creator.apply(input, it, context)) //
.collect(Collectors.toList());
}

@FunctionalInterface
public interface PropertyCreator<T> {
T apply(InputPayloadMetadata payload, PropertyMetadata metadata, PropertyCreationContext context);
}

public static final class PropertyCreationContext {

private final Link link;

private PropertyCreationContext(Link link) {
this.link = link;
}

/**
* {@link Link} for the URI of the resource.
*/
public Link link() {
return link;
}
}

/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

import org.springframework.core.ResolvableType;
import org.springframework.hateoas.AffordanceModel;
import org.springframework.hateoas.AffordanceModel.PropertyMetadata;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.mediatype.hal.HalConfiguration;
Expand Down Expand Up @@ -165,7 +167,7 @@ public HalFormsConfiguration customize(ObjectMapper mapper) {
* @return
*/
public <T> HalFormsConfiguration withOptions(Class<T> type, String property,
Function<PropertyMetadata, HalFormsOptions> creator) {
BiFunction<PropertyMetadata, AffordanceModel.PropertyCreationContext, HalFormsOptions> creator) {

return new HalFormsConfiguration(halConfiguration, patterns, options.withOptions(type, property, creator),
objectMapperCustomizer, mediaTypes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;

import org.springframework.hateoas.AffordanceModel.PayloadMetadata;
import org.springframework.hateoas.AffordanceModel.PropertyMetadata;
import org.springframework.hateoas.AffordanceModel.PropertyCreationContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

Expand All @@ -34,7 +36,7 @@
*/
class HalFormsOptionsFactory {

private final Map<Class<?>, Map<String, Function<PropertyMetadata, HalFormsOptions>>> options;
private final Map<Class<?>, Map<String, BiFunction<PropertyMetadata, PropertyCreationContext, HalFormsOptions>>> options;

/**
* Creates a new, empty {@link HalFormsOptionsFactory}.
Expand All @@ -48,7 +50,7 @@ public HalFormsOptionsFactory() {
*
* @param options must not be {@literal null}.
*/
private HalFormsOptionsFactory(Map<Class<?>, Map<String, Function<PropertyMetadata, HalFormsOptions>>> options) {
private HalFormsOptionsFactory(Map<Class<?>, Map<String, BiFunction<PropertyMetadata, PropertyCreationContext, HalFormsOptions>>> options) {
this.options = options;
}

Expand All @@ -64,13 +66,13 @@ private HalFormsOptionsFactory(Map<Class<?>, Map<String, Function<PropertyMetada
* @see HalFormsOptions#remote(org.springframework.hateoas.Link)
*/
HalFormsOptionsFactory withOptions(Class<?> type, String property,
Function<PropertyMetadata, HalFormsOptions> creator) {
BiFunction<PropertyMetadata, PropertyCreationContext, HalFormsOptions> creator) {

Assert.notNull(type, "Type must not be null!");
Assert.hasText(property, "Property must not be null or empty!");
Assert.notNull(creator, "Creator function must not be null!");

Map<Class<?>, Map<String, Function<PropertyMetadata, HalFormsOptions>>> options = new HashMap<>(this.options);
Map<Class<?>, Map<String, BiFunction<PropertyMetadata, PropertyCreationContext, HalFormsOptions>>> options = new HashMap<>(this.options);

options.compute(type, (it, map) -> {

Expand All @@ -95,22 +97,22 @@ HalFormsOptionsFactory withOptions(Class<?> type, String property,
* @return
*/
@Nullable
HalFormsOptions getOptions(PayloadMetadata payload, PropertyMetadata property) {
HalFormsOptions getOptions(PayloadMetadata payload, PropertyMetadata property, PropertyCreationContext context) {

Assert.notNull(payload, "Payload metadata must not be null!");
Assert.notNull(property, "Property metadata must not be null!");

Class<?> type = payload.getType();
String name = property.getName();

Map<String, Function<PropertyMetadata, HalFormsOptions>> map = options.get(type);
Map<String, BiFunction<PropertyMetadata, PropertyCreationContext, HalFormsOptions>> map = options.get(type);

if (map == null) {
return null;
}

Function<PropertyMetadata, HalFormsOptions> function = map.get(name);
BiFunction<PropertyMetadata, PropertyCreationContext, HalFormsOptions> function = map.get(name);

return function == null ? null : function.apply(property);
return function == null ? null : function.apply(property, context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ public List<HalFormsProperty> createProperties(HalFormsAffordanceModel model) {

HalFormsOptionsFactory optionsFactory = configuration.getOptionsFactory();

return model.createProperties((payload, metadata) -> {
return model.createProperties((payload, metadata, context) -> {

String inputType = metadata.getInputType();
HalFormsOptions options = optionsFactory.getOptions(payload, metadata);
HalFormsOptions options = optionsFactory.getOptions(payload, metadata, context);

HalFormsProperty property = new HalFormsProperty()
.withName(metadata.getName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ void rendersInlineOptions() {
List<String> values = Arrays.asList("1234123412341234", "4321432143214321");

HalFormsConfiguration configuration = new HalFormsConfiguration() //
.withOptions(PatternExample.class, "number", metadata -> HalFormsOptions.inline(values));
.withOptions(PatternExample.class, "number", (metadata, context) -> HalFormsOptions.inline(values));

RepresentationModel<?> models = new RepresentationModel<>(
Affordances.of(Link.of("/example", LinkRelation.of("create"))) //
Expand All @@ -209,7 +209,7 @@ void propagatesSelectedValueToProperty() {

HalFormsConfiguration configuration = new HalFormsConfiguration() //
.withOptions(PatternExample.class, "number",
metadata -> HalFormsOptions.inline(values).withSelectedValue(selected));
(metadata, context) -> HalFormsOptions.inline(values).withSelectedValue(selected));

RepresentationModel<?> models = new RepresentationModel<>(
Affordances.of(Link.of("/example", LinkRelation.of("create"))) //
Expand Down
Loading