Skip to content
Closed
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
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
- Allow Import of Authority Records Without LCCN [MODLD-940](https://folio-org.atlassian.net/browse/MODLD-940)
- Set LINK of the identity resource based on FOLIO configuration [MODLD-923](https://folio-org.atlassian.net/browse/MODLD-923)
- Include tenant ID in cache [MODLD-952](https://folio-org.atlassian.net/browse/MODLD-952)
- Update label of the Title resource to include part number and part name [MODLD-962](https://folio-org.atlassian.net/browse/MODLD-962)

## 1.0.4 (04-24-2025)
- Work Edit form - Instance read-only section: "Notes about the instance" data is not shown [MODLD-716](https://folio-org.atlassian.net/browse/MODLD-716)
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@
<supportingFilesToGenerate>ApiUtil.java</supportingFilesToGenerate>
<generateModelDocumentation>true</generateModelDocumentation>
<templateDirectory>${project.basedir}/src/main/resources/swagger.api/templates</templateDirectory>
<openapiNormalizer>REF_AS_PARENT_IN_ALLOF=true</openapiNormalizer>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this line, the generated PrimaryTitle, ParallelTitle and VariantTitle classes will not extend from the BaseTitle class.

Before this change

public class VariantTitle {
  ...
}

After this change

public class VariantTitle extends BaseTitle {
   ...
}

<configOptions>
<java8>true</java8>
<useTags>true</useTags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import static org.folio.ld.dictionary.PropertyDictionary.PART_NUMBER;
import static org.folio.ld.dictionary.PropertyDictionary.SUBTITLE;
import static org.folio.ld.dictionary.ResourceTypeDictionary.PARALLEL_TITLE;
import static org.folio.linked.data.util.ResourceUtils.getFirstValue;
import static org.folio.linked.data.util.ResourceUtils.putProperty;

import com.fasterxml.jackson.databind.JsonNode;
Expand Down Expand Up @@ -51,7 +50,7 @@ public <P> P toDto(Resource resourceToConvert, P parentDto, ResourceMappingConte
public Resource toEntity(Object dto, Resource parentEntity) {
var parallelTitle = ((ParallelTitleField) dto).getParallelTitle();
var resource = new Resource();
resource.setLabel(getLabel(getFirstValue(parallelTitle::getMainTitle), getFirstValue(parallelTitle::getSubTitle)));
resource.setLabel(getLabel(parallelTitle));
resource.addTypes(PARALLEL_TITLE);
resource.setDoc(getDoc(parallelTitle));
resource.setIdAndRefreshEdges(hashService.hash(resource));
Comment thread
pkjacob marked this conversation as resolved.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import static org.folio.ld.dictionary.PropertyDictionary.PART_NUMBER;
import static org.folio.ld.dictionary.PropertyDictionary.SUBTITLE;
import static org.folio.ld.dictionary.ResourceTypeDictionary.TITLE;
import static org.folio.linked.data.util.ResourceUtils.getFirstValue;
import static org.folio.linked.data.util.ResourceUtils.putProperty;

import com.fasterxml.jackson.databind.JsonNode;
Expand Down Expand Up @@ -48,7 +47,7 @@ public <P> P toDto(Resource resourceToConvert, P parentDto, ResourceMappingConte
public Resource toEntity(Object dto, Resource parentEntity) {
var primaryTitle = ((PrimaryTitleField) dto).getPrimaryTitle();
var resource = new Resource();
resource.setLabel(getLabel(getFirstValue(primaryTitle::getMainTitle), getFirstValue(primaryTitle::getSubTitle)));
resource.setLabel(getLabel(primaryTitle));
resource.addTypes(TITLE);
resource.setDoc(getDoc(primaryTitle));
Comment thread
pkjacob marked this conversation as resolved.
resource.setIdAndRefreshEdges(hashService.hash(resource));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package org.folio.linked.data.mapper.dto.resource.common.title;

import static java.lang.String.join;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static java.util.stream.Collectors.joining;
import static org.folio.linked.data.util.ResourceUtils.getFirstValue;

import java.util.Set;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.folio.linked.data.domain.dto.BaseTitle;
import org.folio.linked.data.domain.dto.HubRequest;
import org.folio.linked.data.domain.dto.HubResponse;
import org.folio.linked.data.domain.dto.InstanceRequest;
Expand All @@ -28,7 +31,14 @@ public Set<Class<?>> supportedParents() {
return SUPPORTED_PARENTS;
}

protected String getLabel(String mainTitle, String subTitle) {
return isBlank(subTitle) ? mainTitle : join(" ", mainTitle, subTitle);
protected String getLabel(BaseTitle title) {
var mainTitle = getFirstValue(title::getMainTitle);
var subTitle = getFirstValue(title::getSubTitle);
var partNumber = getFirstValue(title::getPartNumber);
var partName = getFirstValue(title::getPartName);

return Stream.of(mainTitle, subTitle, partNumber, partName)
.filter(StringUtils::isNotBlank)
.collect(joining(" "));
Comment thread
pkjacob marked this conversation as resolved.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import static org.folio.ld.dictionary.PropertyDictionary.SUBTITLE;
import static org.folio.ld.dictionary.PropertyDictionary.VARIANT_TYPE;
import static org.folio.ld.dictionary.ResourceTypeDictionary.VARIANT_TITLE;
import static org.folio.linked.data.util.ResourceUtils.getFirstValue;
import static org.folio.linked.data.util.ResourceUtils.putProperty;

import com.fasterxml.jackson.databind.JsonNode;
Expand Down Expand Up @@ -52,7 +51,7 @@ public <P> P toDto(Resource resourceToConvert, P parentDto, ResourceMappingConte
public Resource toEntity(Object dto, Resource parentEntity) {
var variantTitle = ((VariantTitleField) dto).getVariantTitle();
var resource = new Resource();
resource.setLabel(getLabel(getFirstValue(variantTitle::getMainTitle), getFirstValue(variantTitle::getSubTitle)));
resource.setLabel(getLabel(variantTitle));
resource.addTypes(VARIANT_TITLE);
resource.setDoc(getDoc(variantTitle));
resource.setIdAndRefreshEdges(hashService.hash(resource));
Comment thread
pkjacob marked this conversation as resolved.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,16 @@ public void setProfileSettings(Integer profileId, CustomProfileSettingsRequestDt
* being used, whether for settings editing or editor rendering.
*/
private CustomProfileSettingsResponseDto defaultToProfile(Integer profileId) {
return new CustomProfileSettingsResponseDto(false, null, profileId);
return new CustomProfileSettingsResponseDto(profileId, false, null);
}
Comment on lines 61 to 63
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

children is marked as required in the OpenAPI schema (customProfileSettings.json), but the default response returns children = null. Consider returning an empty list instead to keep the API response consistent with the schema and avoid clients needing null-handling.

Copilot uses AI. Check for mistakes.

private CustomProfileSettingsResponseDto toDto(Integer profileId, UUID userId, ProfileSettings settings) {
try {
var customProfileSettings = objectMapper.readValue(settings.getSettings(), CustomProfileSettings.class);
return new CustomProfileSettingsResponseDto(
profileId,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order of fields in the generated DTO class got changed due to the change made in pom file.

customProfileSettings.getActive(),
customProfileSettings.getChildren(),
profileId);
customProfileSettings.getChildren());
} catch (JsonProcessingException e) {
log.error("Could not read stored profile settings (user: {}, profile: {}) - default to profile",
userId, profileId);
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/org/folio/linked/data/util/ResourceUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,14 @@ public static List<String> getPrimaryMainTitles(List<TitleFieldRequestTitleInner
.filter(PrimaryTitleField.class::isInstance)
.map(PrimaryTitleField.class::cast)
.map(PrimaryTitleField::getPrimaryTitle)
.map(pt -> join(" ", getFirstValue(pt::getMainTitle), getFirstValue(pt::getSubTitle)))
.map(pt -> join(
" ",
getFirstValue(pt::getMainTitle),
getFirstValue(pt::getSubTitle),
getFirstValue(pt::getPartNumber),
getFirstValue(pt::getPartName)
)
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should move the label generation logic into a new LabelGenerator piece by piece when we change it somehow?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me check this again.

.map(String::trim)
.toList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ protected String postPayload() {
"http://bibfra.me/vocab/library/Title": {
"http://bibfra.me/vocab/library/mainTitle": [
"%s"
],
"http://bibfra.me/vocab/library/subTitle": [
"sub title"
],
"http://bibfra.me/vocab/library/partNumber": [
"part number"
],
"http://bibfra.me/vocab/library/partName": [
"part name"
]
}
}
Expand All @@ -36,24 +45,33 @@ protected String postPayload() {
@SneakyThrows
protected void validateApiResponse(ResultActions apiResponse) {
var hubPath = "$.resource['http://bibfra.me/vocab/lite/Hub']";
var titlePath = hubPath + "['http://bibfra.me/vocab/library/title'][0]['http://bibfra.me/vocab/library/Title']";

apiResponse
.andExpect(jsonPath(hubPath + "['id']").value("-1203724017859497624"))
.andExpect(jsonPath(hubPath + "['http://bibfra.me/vocab/library/title'][0]"
+ "['http://bibfra.me/vocab/library/Title']['http://bibfra.me/vocab/library/mainTitle'][0]")
.value("TEST: HubTitleIT"));
.andExpect(jsonPath(hubPath + "['id']").value("-3606019457490474046"))
.andExpect(jsonPath(titlePath + "['http://bibfra.me/vocab/library/mainTitle'][0]")
.value("TEST: HubTitleIT"))
.andExpect(jsonPath(titlePath + "['http://bibfra.me/vocab/library/subTitle'][0]")
.value("sub title"))
.andExpect(jsonPath(titlePath + "['http://bibfra.me/vocab/library/partNumber'][0]")
.value("part number"))
.andExpect(jsonPath(titlePath + "['http://bibfra.me/vocab/library/partName'][0]")
.value("part name"));
}

@Override
protected void validateGraph(Resource hub) {
var expectedHubLabel = "TEST: HubTitleIT";
var expectedHubLabel = "TEST: HubTitleIT sub title";
validateResourceType(hub, "http://bibfra.me/vocab/lite/Hub");
assertThat(hub.getLabel()).isEqualTo(expectedHubLabel);
assertThat(getProperty(hub, "http://bibfra.me/vocab/lite/label")).isEqualTo(expectedHubLabel);

var title = getFirstOutgoingResource(hub, "http://bibfra.me/vocab/library/title");
validateResourceType(title, "http://bibfra.me/vocab/library/Title");
assertThat(getProperty(title, "http://bibfra.me/vocab/library/mainTitle")).isEqualTo("TEST: HubTitleIT");
assertThat(title.getLabel()).isEqualTo("TEST: HubTitleIT");
assertThat(getProperty(title, "http://bibfra.me/vocab/library/subTitle")).isEqualTo("sub title");
assertThat(getProperty(title, "http://bibfra.me/vocab/library/partNumber")).isEqualTo("part number");
assertThat(getProperty(title, "http://bibfra.me/vocab/library/partName")).isEqualTo("part name");
assertThat(title.getLabel()).isEqualTo("TEST: HubTitleIT sub title part number part name");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,6 @@ void createInstanceWithTitleWithoutMainTitle_shouldReturnBadRequest() throws Exc
.contentType(APPLICATION_JSON)
.headers(defaultHeaders(env))
.content(loadResourceAsString("samples/instance_with_no_main_primary_title.json"));
var expectedError = getError("instance", """
[class PrimaryTitleField {
primaryTitle: class PrimaryTitle {
partName: [Primary: partName]
partNumber: [Primary: partNumber]
mainTitle: []
subTitle: [Primary: subTitle]
nonSortNum: [Primary: nonSortNum]
}
}]""");

// when
var resultActions = mockMvc.perform(requestBuilder);
Expand All @@ -146,7 +136,11 @@ void createInstanceWithTitleWithoutMainTitle_shouldReturnBadRequest() throws Exc
.andReturn().getResponse().getContentAsString();

var errorResponse = objectMapper.readValue(response, ErrorResponse.class);
assertThat(errorResponse.getErrors()).containsOnly(expectedError);
assertThat(errorResponse.getErrors())
.hasSize(1)
.first()
.extracting("code")
.isEqualTo("required_primary_main_title");
}

private Error getError(String resourceType) {
Expand Down