Skip to content

Commit 70a87bd

Browse files
committed
MODLD-981: return Hub's variant and Parallel titles in GET /resource/{id} API response
1 parent b0840a6 commit 70a87bd

File tree

4 files changed

+228
-12
lines changed

4 files changed

+228
-12
lines changed

src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/ParallelTitleMapperUnit.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@
1515
import java.util.HashMap;
1616
import java.util.List;
1717
import lombok.RequiredArgsConstructor;
18-
import org.folio.linked.data.domain.dto.InstanceResponse;
1918
import org.folio.linked.data.domain.dto.ParallelTitle;
2019
import org.folio.linked.data.domain.dto.ParallelTitleField;
2120
import org.folio.linked.data.domain.dto.ParallelTitleFieldResponse;
2221
import org.folio.linked.data.domain.dto.ParallelTitleResponse;
23-
import org.folio.linked.data.domain.dto.WorkResponse;
2422
import org.folio.linked.data.mapper.dto.resource.base.CoreMapper;
2523
import org.folio.linked.data.mapper.dto.resource.base.MapperUnit;
24+
import org.folio.linked.data.model.dto.HasTitle;
2625
import org.folio.linked.data.model.entity.Resource;
2726
import org.folio.linked.data.service.resource.hash.HashService;
2827
import org.springframework.stereotype.Component;
@@ -39,10 +38,9 @@ public class ParallelTitleMapperUnit extends TitleMapperUnit {
3938
public <P> P toDto(Resource resourceToConvert, P parentDto, ResourceMappingContext context) {
4039
var parallelTitle = coreMapper.toDtoWithEdges(resourceToConvert, ParallelTitleResponse.class, false);
4140
parallelTitle.setId(String.valueOf(resourceToConvert.getId()));
42-
if (parentDto instanceof InstanceResponse instance) {
43-
instance.addTitleItem(new ParallelTitleFieldResponse().parallelTitle(parallelTitle));
44-
} else if (parentDto instanceof WorkResponse work) {
45-
work.addTitleItem(new ParallelTitleFieldResponse().parallelTitle(parallelTitle));
41+
var titleField = new ParallelTitleFieldResponse().parallelTitle(parallelTitle);
42+
if (parentDto instanceof HasTitle dtoWithTitle) {
43+
dtoWithTitle.addTitleItem(titleField);
4644
}
4745
return parentDto;
4846
}

src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/VariantTitleMapperUnit.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,13 @@
1616
import java.util.HashMap;
1717
import java.util.List;
1818
import lombok.RequiredArgsConstructor;
19-
import org.folio.linked.data.domain.dto.InstanceResponse;
2019
import org.folio.linked.data.domain.dto.VariantTitle;
2120
import org.folio.linked.data.domain.dto.VariantTitleField;
2221
import org.folio.linked.data.domain.dto.VariantTitleFieldResponse;
2322
import org.folio.linked.data.domain.dto.VariantTitleResponse;
24-
import org.folio.linked.data.domain.dto.WorkResponse;
2523
import org.folio.linked.data.mapper.dto.resource.base.CoreMapper;
2624
import org.folio.linked.data.mapper.dto.resource.base.MapperUnit;
25+
import org.folio.linked.data.model.dto.HasTitle;
2726
import org.folio.linked.data.model.entity.Resource;
2827
import org.folio.linked.data.service.resource.hash.HashService;
2928
import org.springframework.stereotype.Component;
@@ -40,10 +39,9 @@ public class VariantTitleMapperUnit extends TitleMapperUnit {
4039
public <P> P toDto(Resource resourceToConvert, P parentDto, ResourceMappingContext context) {
4140
var variantTitle = coreMapper.toDtoWithEdges(resourceToConvert, VariantTitleResponse.class, false);
4241
variantTitle.setId(String.valueOf(resourceToConvert.getId()));
43-
if (parentDto instanceof InstanceResponse instance) {
44-
instance.addTitleItem(new VariantTitleFieldResponse().variantTitle(variantTitle));
45-
} else if (parentDto instanceof WorkResponse work) {
46-
work.addTitleItem(new VariantTitleFieldResponse().variantTitle(variantTitle));
42+
var titleField = new VariantTitleFieldResponse().variantTitle(variantTitle);
43+
if (parentDto instanceof HasTitle dtoWithTitle) {
44+
dtoWithTitle.addTitleItem(titleField);
4745
}
4846
return parentDto;
4947
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package org.folio.linked.data.e2e.mappings.hub.title;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.folio.ld.dictionary.ResourceTypeDictionary.PARALLEL_TITLE;
5+
import static org.folio.ld.dictionary.ResourceTypeDictionary.TITLE;
6+
import static org.hamcrest.Matchers.hasItem;
7+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
8+
9+
import java.util.List;
10+
import lombok.SneakyThrows;
11+
import org.folio.ld.dictionary.ResourceTypeDictionary;
12+
import org.folio.linked.data.e2e.mappings.PostResourceIT;
13+
import org.folio.linked.data.model.entity.Resource;
14+
import org.springframework.test.web.servlet.ResultActions;
15+
16+
class HubParallelTitleIT extends PostResourceIT {
17+
18+
@Override
19+
protected String postPayload() {
20+
return """
21+
{
22+
"resource": {
23+
"http://bibfra.me/vocab/lite/Hub": {
24+
"profileId": 3,
25+
"http://bibfra.me/vocab/library/title": [
26+
{
27+
"http://bibfra.me/vocab/library/Title": {
28+
"http://bibfra.me/vocab/library/mainTitle": [
29+
"%s"
30+
]
31+
}
32+
},
33+
{
34+
"http://bibfra.me/vocab/library/ParallelTitle":{
35+
"http://bibfra.me/vocab/library/mainTitle":[ "parallel title" ],
36+
"http://bibfra.me/vocab/library/partNumber":[ "part number" ],
37+
"http://bibfra.me/vocab/library/partName":[ "part name" ],
38+
"http://bibfra.me/vocab/library/subTitle":[ "sub title" ],
39+
"http://bibfra.me/vocab/lite/note":[ "note text" ],
40+
"http://bibfra.me/vocab/lite/date":[ "2026" ]
41+
}
42+
}
43+
]
44+
}
45+
}
46+
}"""
47+
.formatted("TEST: " + this.getClass().getSimpleName());
48+
}
49+
50+
@Override
51+
@SneakyThrows
52+
protected void validateApiResponse(ResultActions apiResponse) {
53+
var hubPath = "$.resource['http://bibfra.me/vocab/lite/Hub']";
54+
var titlePath = hubPath + "['http://bibfra.me/vocab/library/title']";
55+
var mainTitlePath = titlePath + "[?(@['http://bibfra.me/vocab/library/Title'])]"
56+
+ "['http://bibfra.me/vocab/library/Title']";
57+
var parallelTitlePath = titlePath + "[?(@['http://bibfra.me/vocab/library/ParallelTitle'])]"
58+
+ "['http://bibfra.me/vocab/library/ParallelTitle']";
59+
60+
apiResponse
61+
.andExpect(jsonPath(mainTitlePath + "['http://bibfra.me/vocab/library/mainTitle'][0]")
62+
.value(hasItem("TEST: HubParallelTitleIT")))
63+
.andExpect(jsonPath(parallelTitlePath + "['http://bibfra.me/vocab/library/mainTitle'][0]")
64+
.value(hasItem("parallel title")))
65+
.andExpect(jsonPath(parallelTitlePath + "['http://bibfra.me/vocab/library/partNumber'][0]")
66+
.value(hasItem("part number")))
67+
.andExpect(jsonPath(parallelTitlePath + "['http://bibfra.me/vocab/library/partName'][0]")
68+
.value(hasItem("part name")))
69+
.andExpect(jsonPath(parallelTitlePath + "['http://bibfra.me/vocab/library/subTitle'][0]")
70+
.value(hasItem("sub title")))
71+
.andExpect(jsonPath(parallelTitlePath + "['http://bibfra.me/vocab/lite/note'][0]")
72+
.value(hasItem("note text")))
73+
.andExpect(jsonPath(parallelTitlePath + "['http://bibfra.me/vocab/lite/date'][0]")
74+
.value(hasItem("2026")));
75+
}
76+
77+
@Override
78+
protected void validateGraph(Resource hub) {
79+
var expectedHubLabel = "TEST: HubParallelTitleIT";
80+
validateResourceType(hub, "http://bibfra.me/vocab/lite/Hub");
81+
assertThat(hub.getLabel()).isEqualTo(expectedHubLabel);
82+
assertThat(getProperty(hub, "http://bibfra.me/vocab/lite/label")).isEqualTo(expectedHubLabel);
83+
84+
var titles = getOutgoingResources(hub, "http://bibfra.me/vocab/library/title");
85+
var mainTitle = getTitleByType(titles, TITLE);
86+
validateResourceType(mainTitle, "http://bibfra.me/vocab/library/Title");
87+
assertThat(getProperty(mainTitle, "http://bibfra.me/vocab/library/mainTitle"))
88+
.isEqualTo("TEST: HubParallelTitleIT");
89+
assertThat(mainTitle.getLabel()).isEqualTo("TEST: HubParallelTitleIT");
90+
91+
var parallelTitle = getTitleByType(titles, PARALLEL_TITLE);
92+
validateResourceType(parallelTitle, "http://bibfra.me/vocab/library/ParallelTitle");
93+
assertThat(getProperty(parallelTitle, "http://bibfra.me/vocab/library/mainTitle"))
94+
.isEqualTo("parallel title");
95+
assertThat(getProperty(parallelTitle, "http://bibfra.me/vocab/library/partNumber"))
96+
.isEqualTo("part number");
97+
assertThat(getProperty(parallelTitle, "http://bibfra.me/vocab/library/partName"))
98+
.isEqualTo("part name");
99+
assertThat(getProperty(parallelTitle, "http://bibfra.me/vocab/library/subTitle"))
100+
.isEqualTo("sub title");
101+
assertThat(getProperty(parallelTitle, "http://bibfra.me/vocab/lite/note"))
102+
.isEqualTo("note text");
103+
assertThat(getProperty(parallelTitle, "http://bibfra.me/vocab/lite/date"))
104+
.isEqualTo("2026");
105+
assertThat(parallelTitle.getLabel()).isEqualTo("parallel title sub title");
106+
}
107+
108+
private Resource getTitleByType(List<Resource> titles, ResourceTypeDictionary type) {
109+
return titles.stream()
110+
.filter(title -> title.isOfType(type))
111+
.findFirst()
112+
.orElseThrow();
113+
}
114+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package org.folio.linked.data.e2e.mappings.hub.title;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.hamcrest.Matchers.hasItem;
5+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
6+
7+
import java.util.List;
8+
import lombok.SneakyThrows;
9+
import org.folio.ld.dictionary.ResourceTypeDictionary;
10+
import org.folio.linked.data.e2e.mappings.PostResourceIT;
11+
import org.folio.linked.data.model.entity.Resource;
12+
import org.springframework.test.web.servlet.ResultActions;
13+
14+
class HubVariantTitleIT extends PostResourceIT {
15+
16+
@Override
17+
protected String postPayload() {
18+
return """
19+
{
20+
"resource": {
21+
"http://bibfra.me/vocab/lite/Hub": {
22+
"profileId": 3,
23+
"http://bibfra.me/vocab/library/title": [
24+
{
25+
"http://bibfra.me/vocab/library/Title": {
26+
"http://bibfra.me/vocab/library/mainTitle": [
27+
"%s"
28+
]
29+
}
30+
},
31+
{
32+
"http://bibfra.me/vocab/library/VariantTitle":{
33+
"http://bibfra.me/vocab/library/mainTitle":[ "variant title" ],
34+
"http://bibfra.me/vocab/library/partNumber":[ "part number" ],
35+
"http://bibfra.me/vocab/library/partName":[ "part name" ],
36+
"http://bibfra.me/vocab/library/subTitle":[ "sub title" ],
37+
"http://bibfra.me/vocab/library/variantType":[ "variant type" ],
38+
"http://bibfra.me/vocab/lite/note":[ "note text" ],
39+
"http://bibfra.me/vocab/lite/date":[ "2026" ]
40+
}
41+
}
42+
]
43+
}
44+
}
45+
}"""
46+
.formatted("TEST: " + this.getClass().getSimpleName());
47+
}
48+
49+
@Override
50+
@SneakyThrows
51+
protected void validateApiResponse(ResultActions apiResponse) {
52+
var hubPath = "$.resource['http://bibfra.me/vocab/lite/Hub']";
53+
var titlePath = hubPath + "['http://bibfra.me/vocab/library/title']";
54+
var mainTitlePath = titlePath + "[?(@['http://bibfra.me/vocab/library/Title'])]"
55+
+ "['http://bibfra.me/vocab/library/Title']";
56+
var variantTitlePath = titlePath + "[?(@['http://bibfra.me/vocab/library/VariantTitle'])]"
57+
+ "['http://bibfra.me/vocab/library/VariantTitle']";
58+
59+
apiResponse
60+
.andExpect(jsonPath(mainTitlePath + "['http://bibfra.me/vocab/library/mainTitle'][0]")
61+
.value(hasItem("TEST: HubVariantTitleIT")))
62+
.andExpect(jsonPath(variantTitlePath + "['http://bibfra.me/vocab/library/mainTitle'][0]")
63+
.value(hasItem("variant title")))
64+
.andExpect(jsonPath(variantTitlePath + "['http://bibfra.me/vocab/library/partNumber'][0]")
65+
.value(hasItem("part number")))
66+
.andExpect(jsonPath(variantTitlePath + "['http://bibfra.me/vocab/library/partName'][0]")
67+
.value(hasItem("part name")))
68+
.andExpect(jsonPath(variantTitlePath + "['http://bibfra.me/vocab/library/subTitle'][0]")
69+
.value(hasItem("sub title")))
70+
.andExpect(jsonPath(variantTitlePath + "['http://bibfra.me/vocab/library/variantType'][0]")
71+
.value(hasItem("variant type")))
72+
.andExpect(jsonPath(variantTitlePath + "['http://bibfra.me/vocab/lite/note'][0]")
73+
.value(hasItem("note text")))
74+
.andExpect(jsonPath(variantTitlePath + "['http://bibfra.me/vocab/lite/date'][0]")
75+
.value(hasItem("2026")));
76+
}
77+
78+
@Override
79+
protected void validateGraph(Resource hub) {
80+
var titles = getOutgoingResources(hub, "http://bibfra.me/vocab/library/title");
81+
var variantTitle = getVariantTitle(titles);
82+
83+
assertThat(getProperty(variantTitle, "http://bibfra.me/vocab/library/mainTitle"))
84+
.isEqualTo("variant title");
85+
assertThat(getProperty(variantTitle, "http://bibfra.me/vocab/library/partNumber"))
86+
.isEqualTo("part number");
87+
assertThat(getProperty(variantTitle, "http://bibfra.me/vocab/library/partName"))
88+
.isEqualTo("part name");
89+
assertThat(getProperty(variantTitle, "http://bibfra.me/vocab/library/subTitle"))
90+
.isEqualTo("sub title");
91+
assertThat(getProperty(variantTitle, "http://bibfra.me/vocab/library/variantType"))
92+
.isEqualTo("variant type");
93+
assertThat(getProperty(variantTitle, "http://bibfra.me/vocab/lite/note"))
94+
.isEqualTo("note text");
95+
assertThat(getProperty(variantTitle, "http://bibfra.me/vocab/lite/date"))
96+
.isEqualTo("2026");
97+
assertThat(variantTitle.getLabel()).isEqualTo("variant title sub title");
98+
}
99+
100+
private Resource getVariantTitle(List<Resource> titles) {
101+
return titles.stream()
102+
.filter(title -> title.isOfType(ResourceTypeDictionary.VARIANT_TITLE))
103+
.findFirst()
104+
.orElseThrow();
105+
}
106+
}

0 commit comments

Comments
 (0)