Skip to content

Commit 44847ec

Browse files
authored
Merge pull request #11704 from IQSS/11703-return-isDefault-property-get-dataset-templates
Templates and Notifications API fixes
2 parents 5e0dd5b + 541fd21 commit 44847ec

File tree

11 files changed

+375
-27
lines changed

11 files changed

+375
-27
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Release Notes
2+
3+
## Templates API fixes
4+
- Added the missing `isDefault` field to the **Get Dataset Templates** API response.
5+
- Added the missing `fileAccessRequest` field of terms of use and access to the **Get Dataset Templates** API response.
6+
- Added the missing `contactForAccess` field of terms of use and access to the **Get Dataset Templates** API response.
7+
- Resolved an API **500 error** that occurred when working with templates containing custom license terms.
8+
- Updated API behavior so templates are **no longer returned from parent dataverses** when the "Include Templates from Root" option is unchecked in the UI.
9+
10+
## Notifications API fixes
11+
- Fixed API errors caused by NullPointerException when retrieving notifications without a requestor.
12+
13+
See #11704

src/main/java/edu/harvard/iq/dataverse/api/dto/NewTemplateDTO.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public Template toTemplate() {
3838
template.updateInstructions();
3939
template.setCreateTime(new Timestamp(new Date().getTime()));
4040
template.setUsageCount(0L);
41+
template.setIsDefaultForDataverse(isDefault);
4142

4243
return template;
4344
}

src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateTemplateCommand.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,14 @@ public Template execute(CommandContext ctxt) throws CommandException {
4848
DatasetFieldUtil.tidyUpFields(template.getDatasetFields(), false);
4949
}
5050

51-
return ctxt.templates().save(template);
51+
Template createdTemplate = ctxt.templates().save(template);
52+
53+
if (initialize && template.isIsDefaultForDataverse()) {
54+
dataverse.setDefaultTemplate(createdTemplate);
55+
ctxt.em().merge(dataverse);
56+
}
57+
58+
return template;
5259
}
5360

5461
private static void updateTermsOfUseAndAccess(CommandContext ctxt, Template template) {

src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ListDataverseTemplatesCommand.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,22 @@ public ListDataverseTemplatesCommand(DataverseRequest request, Dataverse dataver
2626

2727
@Override
2828
public List<Template> execute(CommandContext ctxt) throws CommandException {
29-
List<Template> templates = new ArrayList<>();
29+
List<Template> availableTemplates = new ArrayList<>(dataverse.getTemplates());
3030

31-
if (dataverse.getOwner() != null) {
32-
templates.addAll(dataverse.getParentTemplates());
31+
if (!dataverse.isTemplateRoot() && dataverse.getOwner() != null) {
32+
availableTemplates.addAll(dataverse.getParentTemplates());
3333
}
3434

35-
templates.addAll(dataverse.getTemplates());
35+
setDefaultTemplate(availableTemplates);
3636

37-
return templates;
37+
return availableTemplates;
38+
}
39+
40+
private void setDefaultTemplate(List<Template> availableTemplates) {
41+
Optional.ofNullable(dataverse.getDefaultTemplate())
42+
.map(Template::getId).flatMap(defaultTemplateId -> availableTemplates.stream()
43+
.filter(template -> template.getId().equals(defaultTemplateId))
44+
.findFirst())
45+
.ifPresent(template -> template.setIsDefaultForDataverse(true));
3846
}
3947
}

src/main/java/edu/harvard/iq/dataverse/util/json/InAppNotificationsJsonPrinter.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,11 @@ private void addDatasetCreatedFields(final NullSafeJsonBuilder notificationJson,
195195
}
196196

197197
private void addRequestorFields(final NullSafeJsonBuilder notificationJson, final AuthenticatedUser requestor) {
198-
notificationJson.add(KEY_REQUESTOR_FIRST_NAME, requestor.getFirstName());
199-
notificationJson.add(KEY_REQUESTOR_LAST_NAME, requestor.getLastName());
200-
notificationJson.add(KEY_REQUESTOR_EMAIL, requestor.getEmail());
198+
if (requestor != null) {
199+
notificationJson.add(KEY_REQUESTOR_FIRST_NAME, requestor.getFirstName());
200+
notificationJson.add(KEY_REQUESTOR_LAST_NAME, requestor.getLastName());
201+
notificationJson.add(KEY_REQUESTOR_EMAIL, requestor.getEmail());
202+
}
201203
}
202204

203205
private void addDatasetFields(final NullSafeJsonBuilder notificationJson, final UserNotification userNotification) {

src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,7 @@ public static JsonObjectBuilder jsonTemplate(Template template) {
15921592
return jsonObjectBuilder()
15931593
.add("id", template.getId())
15941594
.add("name", template.getName())
1595+
.add("isDefault", template.isIsDefaultForDataverse())
15951596
.add("usageCount", template.getUsageCount())
15961597
.add("createTime", template.getCreateTime().toString())
15971598
.add("createDate", template.getCreateDate())
@@ -1602,9 +1603,10 @@ public static JsonObjectBuilder jsonTemplate(Template template) {
16021603
}
16031604

16041605
public static JsonObjectBuilder jsonTermsOfUseAndAccess(TermsOfUseAndAccess termsOfUseAndAccess) {
1606+
License license = termsOfUseAndAccess.getLicense();
16051607
return jsonObjectBuilder()
16061608
.add("id", termsOfUseAndAccess.getId())
1607-
.add("license", json(termsOfUseAndAccess.getLicense()))
1609+
.add("license", license != null ? json(license) : null)
16081610
.add("termsOfUse", termsOfUseAndAccess.getTermsOfUse())
16091611
.add("termsOfAccess", termsOfUseAndAccess.getTermsOfAccess())
16101612
.add("confidentialityDeclaration", termsOfUseAndAccess.getConfidentialityDeclaration())
@@ -1618,7 +1620,9 @@ public static JsonObjectBuilder jsonTermsOfUseAndAccess(TermsOfUseAndAccess term
16181620
.add("originalArchive", termsOfUseAndAccess.getOriginalArchive())
16191621
.add("availabilityStatus", termsOfUseAndAccess.getAvailabilityStatus())
16201622
.add("sizeOfCollection", termsOfUseAndAccess.getSizeOfCollection())
1621-
.add("studyCompletion", termsOfUseAndAccess.getStudyCompletion());
1623+
.add("studyCompletion", termsOfUseAndAccess.getStudyCompletion())
1624+
.add("contactForAccess", termsOfUseAndAccess.getContactForAccess())
1625+
.add("fileAccessRequest", termsOfUseAndAccess.isFileAccessRequest());
16221626
}
16231627

16241628
public static JsonArrayBuilder jsonTemplateInstructions(Map<String, String> templateInstructions) {

src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,6 +2335,7 @@ public void testCreateAndGetTemplates() {
23352335
);
23362336
createTemplateResponse.then().assertThat().statusCode(OK.getStatusCode())
23372337
.body("data.name", equalTo("Dataverse template"))
2338+
.body("data.isDefault", equalTo(true))
23382339
.body("data.usageCount", equalTo(0))
23392340
.body("data.termsOfUseAndAccess.license.name", equalTo("CC0 1.0"))
23402341
.body("data.datasetFields.citation.fields.size()", equalTo(1))
@@ -2358,6 +2359,7 @@ public void testCreateAndGetTemplates() {
23582359
getTemplateResponse.then().assertThat().statusCode(OK.getStatusCode())
23592360
.body("data.size()", equalTo(1))
23602361
.body("data[0].name", equalTo("Dataverse template"))
2362+
.body("data[0].isDefault", equalTo(true))
23612363
.body("data[0].usageCount", equalTo(0))
23622364
.body("data[0].termsOfUseAndAccess.license.name", equalTo("CC0 1.0"))
23632365
.body("data[0].datasetFields.citation.fields.size()", equalTo(1))

src/test/java/edu/harvard/iq/dataverse/engine/command/impl/ListDataverseTemplatesCommandTest.java

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
import edu.harvard.iq.dataverse.engine.command.CommandContext;
66
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
77
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
8+
import edu.harvard.iq.dataverse.util.template.TemplateBuilder;
89
import org.junit.jupiter.api.BeforeEach;
910
import org.junit.jupiter.api.Test;
1011
import org.mockito.Mockito;
1112

13+
import java.util.Arrays;
1214
import java.util.Collections;
1315
import java.util.List;
1416

1517
import static org.junit.jupiter.api.Assertions.assertEquals;
18+
import static org.junit.jupiter.api.Assertions.assertFalse;
19+
import static org.junit.jupiter.api.Assertions.assertNotNull;
1620
import static org.junit.jupiter.api.Assertions.assertTrue;
1721

1822
public class ListDataverseTemplatesCommandTest {
@@ -28,52 +32,138 @@ public void setUp() {
2832

2933
@Test
3034
public void execute_shouldReturnTemplates_noParent() throws CommandException {
35+
// Arrange
3136
Dataverse dataverseMock = Mockito.mock(Dataverse.class);
32-
3337
Mockito.when(dataverseMock.getTemplates()).thenReturn(Collections.singletonList(testTemplate));
3438

3539
ListDataverseTemplatesCommand sut = new ListDataverseTemplatesCommand(dataverseRequestStub, dataverseMock);
3640

41+
// Act
3742
List<Template> result = sut.execute(Mockito.mock(CommandContext.class));
3843

44+
// Assert
3945
assertEquals(1, result.size());
4046
assertEquals(testTemplate, result.get(0));
4147
}
4248

4349
@Test
4450
public void execute_shouldReturnTemplates_parentHasTemplates() throws CommandException {
51+
// Arrange
4552
Template parentTemplate = new Template();
46-
4753
Dataverse dataverseMock = Mockito.mock(Dataverse.class);
4854
Dataverse parentDataverseMock = Mockito.mock(Dataverse.class);
49-
5055
Mockito.when(dataverseMock.getTemplates()).thenReturn(Collections.singletonList(testTemplate));
5156
Mockito.when(dataverseMock.getParentTemplates()).thenReturn(Collections.singletonList(parentTemplate));
5257
Mockito.when(dataverseMock.getOwner()).thenReturn(parentDataverseMock);
5358

5459
ListDataverseTemplatesCommand sut = new ListDataverseTemplatesCommand(dataverseRequestStub, dataverseMock);
5560

61+
// Act
5662
List<Template> result = sut.execute(Mockito.mock(CommandContext.class));
5763

64+
// Assert
5865
assertEquals(2, result.size());
5966
assertTrue(result.contains(testTemplate));
6067
assertTrue(result.contains(parentTemplate));
6168
}
6269

70+
@Test
71+
public void execute_shouldNotIncludeParentTemplates_whenDataverseIsRoot() throws CommandException {
72+
// Arrange
73+
String parentTemplateName = "parentTemplate";
74+
Template parentTemplate = TemplateBuilder.aTemplate().withName(parentTemplateName).build();
75+
String childTemplateName = "childTemplateName";
76+
Template childTemplate = TemplateBuilder.aTemplate().withName(childTemplateName).build();
77+
Dataverse dataverseMock = Mockito.mock(Dataverse.class);
78+
Dataverse parentDataverseMock = Mockito.mock(Dataverse.class);
79+
Mockito.when(dataverseMock.getTemplates()).thenReturn(Collections.singletonList(childTemplate));
80+
Mockito.when(dataverseMock.getParentTemplates()).thenReturn(Collections.singletonList(parentTemplate));
81+
Mockito.when(dataverseMock.getOwner()).thenReturn(parentDataverseMock);
82+
Mockito.when(dataverseMock.isTemplateRoot()).thenReturn(true);
83+
84+
ListDataverseTemplatesCommand sut = new ListDataverseTemplatesCommand(dataverseRequestStub, dataverseMock);
85+
86+
// Act
87+
List<Template> result = sut.execute(Mockito.mock(CommandContext.class));
88+
89+
// Assert
90+
assertEquals(1, result.size());
91+
assertTrue(result.get(0).getName().equals(childTemplateName));
92+
}
93+
94+
6395
@Test
6496
public void execute_shouldReturnTemplates_parentHasNoTemplates() throws CommandException {
97+
// Arrange
6598
Dataverse dataverseMock = Mockito.mock(Dataverse.class);
6699
Dataverse parentDataverseStub = Mockito.mock(Dataverse.class);
67-
68100
Mockito.when(dataverseMock.getTemplates()).thenReturn(Collections.singletonList(testTemplate));
69101
Mockito.when(dataverseMock.getOwner()).thenReturn(parentDataverseStub);
70102
Mockito.when(dataverseMock.getParentTemplates()).thenReturn(Collections.emptyList());
71103

72104
ListDataverseTemplatesCommand sut = new ListDataverseTemplatesCommand(dataverseRequestStub, dataverseMock);
73105

106+
// Act
74107
List<Template> result = sut.execute(Mockito.mock(CommandContext.class));
75108

109+
// Assert
76110
assertEquals(1, result.size());
77111
assertTrue(result.contains(testTemplate));
78112
}
113+
114+
115+
@Test
116+
public void execute_shouldSetDefaultTemplate_whenDefaultIsPresent() throws CommandException {
117+
// Arrange
118+
String defaultTplName = "defaultTplName";
119+
String otherTplName = "otherTplName";
120+
121+
Template defaultTpl = TemplateBuilder.aTemplate().withName(defaultTplName).isDefault(true).build();
122+
Template otherTpl = TemplateBuilder.aTemplate().withName(otherTplName).isDefault(false).build();
123+
124+
Dataverse dataverseMock = Mockito.mock(Dataverse.class);
125+
Mockito.when(dataverseMock.getTemplates()).thenReturn(Arrays.asList(defaultTpl, otherTpl));
126+
Mockito.when(dataverseMock.getDefaultTemplate()).thenReturn(defaultTpl);
127+
128+
ListDataverseTemplatesCommand sut = new ListDataverseTemplatesCommand(dataverseRequestStub, dataverseMock);
129+
130+
// Act
131+
List<Template> result = sut.execute(Mockito.mock(CommandContext.class));
132+
133+
// Assert
134+
assertEquals(2, result.size());
135+
136+
Template resultDefault = findTemplateByName(result, defaultTplName);
137+
assertNotNull(resultDefault, "Default template should be in the list");
138+
assertTrue(resultDefault.isIsDefaultForDataverse(), "The template with name " + defaultTplName + " should be marked as default");
139+
140+
Template resultOther = findTemplateByName(result, otherTplName);
141+
assertNotNull(resultOther, "Other template should be in the list");
142+
assertFalse(resultOther.isIsDefaultForDataverse(), "The template with name " + otherTplName + " should NOT be marked as default");
143+
}
144+
145+
@Test
146+
public void execute_shouldNotSetDefault_whenNoDefaultTemplateExists() throws CommandException {
147+
// Arrange
148+
testTemplate = TemplateBuilder.aTemplate().isDefault(false).build();
149+
Dataverse dataverseMock = Mockito.mock(Dataverse.class);
150+
Mockito.when(dataverseMock.getTemplates()).thenReturn(Collections.singletonList(testTemplate));
151+
Mockito.when(dataverseMock.getDefaultTemplate()).thenReturn(null);
152+
153+
ListDataverseTemplatesCommand sut = new ListDataverseTemplatesCommand(dataverseRequestStub, dataverseMock);
154+
155+
// Act
156+
List<Template> result = sut.execute(Mockito.mock(CommandContext.class));
157+
158+
// Assert
159+
assertEquals(1, result.size());
160+
assertFalse(result.get(0).isIsDefaultForDataverse(), "No template should be marked as default");
161+
}
162+
163+
private Template findTemplateByName(List<Template> templates, String name) {
164+
return templates.stream()
165+
.filter(t -> name.equals(t.getName()))
166+
.findFirst()
167+
.orElse(null);
168+
}
79169
}

src/test/java/edu/harvard/iq/dataverse/util/json/InAppNotificationsJsonPrinterTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,26 @@ public void testAddFieldsByType_requestFileAccess() {
229229
verify(notificationJson).add(KEY_DATAFILE_DISPLAY_NAME, "Test File");
230230
}
231231

232+
@Test
233+
public void testAddFieldsByType_requestFileAccess_nullRequestor() {
234+
userNotification.setType(UserNotification.Type.REQUESTFILEACCESS);
235+
userNotification.setObjectId(1L);
236+
userNotification.setRequestor(null);
237+
238+
DataFile dataFile = mock(DataFile.class);
239+
when(dataFile.getId()).thenReturn(1L);
240+
when(dataFile.getDisplayName()).thenReturn("Test File");
241+
when(dataFileService.find(1L)).thenReturn(dataFile);
242+
243+
sut.addFieldsByType(notificationJson, authenticatedUser, userNotification);
244+
245+
verify(notificationJson, never()).add(eq(KEY_REQUESTOR_FIRST_NAME), anyString());
246+
verify(notificationJson, never()).add(eq(KEY_REQUESTOR_LAST_NAME), anyString());
247+
verify(notificationJson, never()).add(eq(KEY_REQUESTOR_EMAIL), anyString());
248+
verify(notificationJson).add(KEY_DATAFILE_ID, Long.valueOf("1"));
249+
verify(notificationJson).add(KEY_DATAFILE_DISPLAY_NAME, "Test File");
250+
}
251+
232252
@Test
233253
public void testAddFieldsByType_grantFileAccess() {
234254
userNotification.setType(UserNotification.Type.GRANTFILEACCESS);

0 commit comments

Comments
 (0)