Skip to content

Commit

Permalink
Provide a property creation context to HalFormsOptionsFactory
Browse files Browse the repository at this point in the history
  • Loading branch information
reda-alaoui committed Dec 23, 2024
1 parent 1c3eab8 commit 93209ce
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 15 deletions.
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

0 comments on commit 93209ce

Please sign in to comment.