Skip to content

Commit

Permalink
fix titles and descriptions of nested properties
Browse files Browse the repository at this point in the history
This makes the titles and descriptions of the HAL-FORMS profile endpoint consistent with the titles and descriptions of the json-schema profile endpoint
  • Loading branch information
NielsCW committed Dec 23, 2024
1 parent 02b285a commit cc732c0
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.data.rest.webmvc.RootResourceInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.hateoas.mediatype.MessageResolver;

@RequiredArgsConstructor
Expand Down Expand Up @@ -92,12 +93,27 @@ private String getType(Property property) {
}

private String readDescription(RootResourceInformation information, List<Property> properties) {
var description = messageResolver.resolve(DescriptionMessageSourceResolvable.forNestedProperty(information, properties));
String description = null;
if (properties.size() == 1) {
description = messageResolver.resolve(DescriptionMessageSourceResolvable.forProperty(information,
properties.get(0)));
} else if (properties.size() > 1) {
var type = properties.get(properties.size() - 2).getTypeInformation();
var property = properties.get(properties.size() - 1);
description = messageResolver.resolve(DescriptionMessageSourceResolvable.forNestedProperty(type, property));
}
return description == null ? "" : description;
}

private String readTitle(RootResourceInformation information, List<Property> properties) {
return messageResolver.resolve(TitleMessageSourceResolvable.forNestedProperty(information, properties));
TypeInformation<?> type;
if (properties.size() > 1) {
type = properties.get(properties.size() - 2).getTypeInformation();
} else {
type = information.getPersistentEntity().getTypeInformation();
}
return messageResolver.resolve(TitleMessageSourceResolvable.forProperty(type, properties.get(
properties.size() - 1)));
}

private String readPrompt(RootResourceInformation information, String path) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
package com.contentgrid.spring.data.rest.webmvc.blueprint;

import com.contentgrid.spring.data.rest.mapping.Property;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Value;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.data.rest.webmvc.RootResourceInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.StringUtils;

@Value
public class DescriptionMessageSourceResolvable implements MessageSourceResolvable {
String[] codes;

public static DescriptionMessageSourceResolvable forEntity(RootResourceInformation information) {
return forNestedProperty(information, List.of());
// e.g. "rest.description.d\:person"
return new DescriptionMessageSourceResolvable(information.getResourceMetadata().getItemResourceDescription().getMessage());
}

public static DescriptionMessageSourceResolvable forProperty(RootResourceInformation information, Property property) {
return forNestedProperty(information, List.of(property));
// e.g. "rest.description.d\:person.firstName"
return new DescriptionMessageSourceResolvable(information.getResourceMetadata().getItemResourceDescription().getMessage() + "." + property.getName());
}

public static DescriptionMessageSourceResolvable forNestedProperty(RootResourceInformation information, Collection<Property> properties) {
var message = properties.stream()
.map(Property::getName)
.map(name -> "." + name)
.collect(Collectors.joining());
return new DescriptionMessageSourceResolvable(information.getResourceMetadata().getItemResourceDescription().getMessage() + message);
public static DescriptionMessageSourceResolvable forNestedProperty(TypeInformation<?> information, Property property) {
// e.g. "rest.description.auditMetadata.createdDate"
var className = StringUtils.uncapitalize(information.getType().getSimpleName());
var code = "rest.description.%s.%s".formatted(className, property.getName());
return new DescriptionMessageSourceResolvable(code);
}

private DescriptionMessageSourceResolvable(String... codes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.core.mapping.ResourceMappings;
import org.springframework.data.rest.webmvc.RootResourceInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.hateoas.LinkRelation;
import org.springframework.hateoas.mediatype.MessageResolver;
import org.springframework.hateoas.mediatype.hal.HalLinkRelation;
Expand Down Expand Up @@ -63,7 +64,7 @@ public EntityRepresentationModel toModel(RootResourceInformation information) {

return EntityRepresentationModel.builder()
.name(name)
.title(readTitle(information))
.title(readTitle(entityContainer.getTypeInformation()))
.description(readDescription(information))
.attributes(attributes)
.relations(relations)
Expand All @@ -75,7 +76,7 @@ private String readDescription(RootResourceInformation information) {
return description == null ? "" : description;
}

private String readTitle(RootResourceInformation information) {
private String readTitle(TypeInformation<?> information) {
return messageResolver.resolve(TitleMessageSourceResolvable.forEntity(information));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ private String readDescription(RootResourceInformation information, Property pro
}

private String readTitle(RootResourceInformation information, Property property) {
return messageResolver.resolve(TitleMessageSourceResolvable.forProperty(information, property));
return messageResolver.resolve(TitleMessageSourceResolvable.forProperty(
information.getPersistentEntity().getTypeInformation(), property));
}

}
Original file line number Diff line number Diff line change
@@ -1,31 +1,21 @@
package com.contentgrid.spring.data.rest.webmvc.blueprint;

import com.contentgrid.spring.data.rest.mapping.Property;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Value;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.data.rest.webmvc.RootResourceInformation;
import org.springframework.data.util.TypeInformation;

@Value
public class TitleMessageSourceResolvable implements MessageSourceResolvable {
String[] codes;

public static TitleMessageSourceResolvable forEntity(RootResourceInformation information) {
return forNestedProperty(information, List.of());
public static TitleMessageSourceResolvable forEntity(TypeInformation<?> information) {
return new TitleMessageSourceResolvable(information.getType().getName() + "._title");
}

public static TitleMessageSourceResolvable forProperty(RootResourceInformation information, Property property) {
return forNestedProperty(information, List.of(property));
}

public static TitleMessageSourceResolvable forNestedProperty(RootResourceInformation information, Collection<Property> properties) {
var message = properties.stream()
.map(Property::getName)
.map(name -> "." + name)
.collect(Collectors.joining());
return new TitleMessageSourceResolvable(information.getDomainType().getName() + message + "._title");
public static TitleMessageSourceResolvable forProperty(TypeInformation<?> information, Property property) {
var code = information.getType().getName() + "." + property.getName() + "._title";
return new TitleMessageSourceResolvable(code);
}

private TitleMessageSourceResolvable(String... codes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,8 +354,9 @@ void profileController_entityInformation_withEmbeddedContent() throws Exception
"blueprint:attribute": [
{
name: "length",
title: "Content Length",
type: "long",
description: "",
description: "Length of the content",
readOnly: true,
required: false,
_embedded: {
Expand All @@ -369,8 +370,9 @@ void profileController_entityInformation_withEmbeddedContent() throws Exception
},
{
name: "mimetype",
title: "Content Mimetype",
type: "string",
description: "",
description: "Mimetype of the content",
readOnly: false,
required: false,
_embedded: {
Expand All @@ -385,8 +387,9 @@ void profileController_entityInformation_withEmbeddedContent() throws Exception
},
{
name: "filename",
title: "Content Filename",
type: "string",
description: "",
description: "Filename of the content",
readOnly: false,
required: false,
_embedded: {
Expand Down Expand Up @@ -737,8 +740,9 @@ void profileController_entityInformation_entityNameWithDashes() throws Exception
"blueprint:attribute": [
{
name: "length",
title: "Content Length",
type: "long",
description: "",
description: "Length of the content",
readOnly: true,
required: false,
_embedded: {
Expand All @@ -747,8 +751,9 @@ void profileController_entityInformation_entityNameWithDashes() throws Exception
},
{
name: "mimetype",
title: "Content Mimetype",
type: "string",
description: "",
description: "Mimetype of the content",
readOnly: false,
required: false,
_embedded: {
Expand All @@ -757,8 +762,9 @@ void profileController_entityInformation_entityNameWithDashes() throws Exception
},
{
name: "filename",
title: "Content Filename",
type: "string",
description: "",
description: "Filename of the content",
readOnly: false,
required: false,
_embedded: {
Expand All @@ -778,8 +784,9 @@ void profileController_entityInformation_entityNameWithDashes() throws Exception
"blueprint:attribute": [
{
name: "length",
title: "Content Length",
type: "long",
description: "",
description: "Length of the content",
readOnly: true,
required: false,
_embedded: {
Expand All @@ -788,8 +795,9 @@ void profileController_entityInformation_entityNameWithDashes() throws Exception
},
{
name: "mimetype",
title: "Content Mimetype",
type: "string",
description: "",
description: "Mimetype of the content",
readOnly: false,
required: false,
_embedded: {
Expand All @@ -798,8 +806,9 @@ void profileController_entityInformation_entityNameWithDashes() throws Exception
},
{
name: "filename",
title: "Content Filename",
type: "string",
description: "",
description: "Filename of the content",
readOnly: false,
required: false,
_embedded: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ com.contentgrid.spring.test.fixture.invoicing.model.Invoice.attachment_filename.
com.contentgrid.spring.test.fixture.invoicing.model.Invoice.attachment_mimetype._prompt=Attached File Mimetype
com.contentgrid.spring.test.fixture.invoicing.model.Customer.content.filename._prompt=Customer Document Filename
com.contentgrid.spring.test.fixture.invoicing.model.Customer.content.mimetype._prompt=Customer Document Mimetype
com.contentgrid.spring.test.fixture.invoicing.model.support.Content.filename._title=Content Filename
com.contentgrid.spring.test.fixture.invoicing.model.support.Content.mimetype._title=Content Mimetype
com.contentgrid.spring.test.fixture.invoicing.model.support.Content.length._title=Content Length
rest.description.d\:customer=Company or person that acts like a client
rest.description.d\:customer.name=Full name of the customer
rest.description.d\:customer.vat=VAT number of the customer
Expand All @@ -19,3 +22,6 @@ rest.description.d\:invoice=A bill containing a counterparty and several orders
rest.description.d\:invoice.number=Identifier of the invoice
rest.description.d\:invoice.counterparty=Client that has to pay the invoice
rest.description.d\:invoice.orders=Orders of the invoice
rest.description.content.filename=Filename of the content
rest.description.content.mimetype=Mimetype of the content
rest.description.content.length=Length of the content

0 comments on commit cc732c0

Please sign in to comment.