Skip to content
Open
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
15 changes: 15 additions & 0 deletions doc/release-notes/11914-set-template-default-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## New Endpoint: POST `/dataverses/{id}/template/default/{templateId}`

A new endpoint has been implemented to set the default template to a given dataverse collection.

### Functionality
- Sets the default template of the given dataverse collection.
- You must have edit dataverse permission in the collection in order to use this endpoint.

## New Endpoint: DELETE `/dataverses/{id}/template/default`
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

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

The endpoint path in the documentation uses /template/default (singular "template"), but based on the actual implementation in Dataverses.java the path is /templates/default (plural "templates"). Update the documentation to use the correct plural form: /dataverses/{id}/templates/default.

Copilot uses AI. Check for mistakes.

A new endpoint has been implemented to remove the default template to a given dataverse collection.

### Functionality
- Removes the default template of the given dataverse collection.
- You must have edit dataverse permission in the collection in order to use this endpoint.
14 changes: 14 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,20 @@ protected Dataverse findDataverseOrDie( String dvIdtf ) throws WrappedResponse {
}
return dv;
}

protected Template findTemplateOrDie(Long templateId, Dataverse dataverse) throws WrappedResponse {

Template template = dataverse.getTemplates().stream()
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need to take into account whether the dataverse is inheriting templates from its parents.

.filter(t -> Objects.equals(t.getId(), templateId))
.findFirst()
.orElse(null);

if (template == null) {
throw new WrappedResponse(
error(Response.Status.NOT_FOUND, "Can't find template with identifier='" + templateId + "'"));
}
return template;
}

protected DataverseLinkingDataverse findDataverseLinkingDataverseOrDie(String dataverseId, String linkedDataverseId) throws WrappedResponse {
DataverseLinkingDataverse dvld;
Expand Down
39 changes: 39 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java
Original file line number Diff line number Diff line change
Expand Up @@ -2002,6 +2002,45 @@ public Response createTemplate(@Context ContainerRequestContext crc, String body
}
}

@POST
@AuthRequired
@Path("{identifier}/templates/default/{templateId}")
public Response setDefaultTemplate(@Context ContainerRequestContext crc,
@PathParam("identifier") String dvId,
@PathParam("templateId") Long templateId) {

try {

Dataverse dataverse = findDataverseOrDie(dvId);
Template template = findTemplateOrDie(templateId, dataverse);
DataverseRequest dvReq = createDataverseRequest(getRequestUser(crc));
SetDefaultTemplateCommand command = new SetDefaultTemplateCommand(template, dvReq, dataverse);

execCommand(command);

return ok(BundleUtil.getStringFromBundle("dataverse.setDefaultTemplate.success"));

} catch (WrappedResponse e) {
return e.getResponse();
}
}

@DELETE
@AuthRequired
@Path("{identifier}/templates/default")
public Response removeDefaultTemplate(@Context ContainerRequestContext crc,
@PathParam("identifier") String dvId) {
try {
Dataverse dataverse = findDataverseOrDie(dvId);
RemoveDefaultDatasetCommand command = new RemoveDefaultDatasetCommand(createDataverseRequest(getRequestUser(crc)), dataverse);
execCommand(command);
return ok(BundleUtil.getStringFromBundle("dataverse.removeDefaultTemplate.success"));
} catch (WrappedResponse e) {
return e.getResponse();
}
}


@GET
@AuthRequired
@Path("{identifier}/allowedMetadataLanguages")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ public Template execute(CommandContext ctxt) throws CommandException {
if (initialize && template.isIsDefaultForDataverse()) {
dataverse.setDefaultTemplate(createdTemplate);
ctxt.em().merge(dataverse);
ctxt.em().flush();
}

return template;
return createdTemplate;
}

private static void updateTermsOfUseAndAccess(CommandContext ctxt, Template template) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package edu.harvard.iq.dataverse.engine.command.impl;

import edu.harvard.iq.dataverse.*;
import edu.harvard.iq.dataverse.authorization.Permission;

import edu.harvard.iq.dataverse.engine.command.AbstractCommand;
import edu.harvard.iq.dataverse.engine.command.CommandContext;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.engine.command.RequiredPermissions;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;

/**
* @author J.P. Tosca
* Removes the default template {@link Template} for a {@link Dataverse}.
*/
@RequiredPermissions(Permission.EditDataverse)
public class RemoveDefaultDatasetCommand extends AbstractCommand<Dataverse>{

private final Dataverse dataverse;

public RemoveDefaultDatasetCommand(DataverseRequest request, Dataverse dataverse) {
super(request, dataverse);
this.dataverse = dataverse;
}

@Override
public Dataverse execute(CommandContext ctxt) throws CommandException {
dataverse.setDefaultTemplate(null);
return dataverse;
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

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

The command modifies the dataverse but doesn't persist the changes to the database. After calling dataverse.setDefaultTemplate(null), you should merge the dataverse entity using ctxt.em().merge(dataverse) to ensure the changes are persisted. See similar commands like CreateTemplateCommand (line 55) for reference.

Suggested change
return dataverse;
Dataverse mergedDataverse = ctxt.em().merge(dataverse);
return mergedDataverse;

Copilot uses AI. Check for mistakes.
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package edu.harvard.iq.dataverse.engine.command.impl;

import edu.harvard.iq.dataverse.*;
import edu.harvard.iq.dataverse.authorization.Permission;

import edu.harvard.iq.dataverse.engine.command.AbstractCommand;
import edu.harvard.iq.dataverse.engine.command.CommandContext;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.engine.command.RequiredPermissions;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
import edu.harvard.iq.dataverse.Template;

/**
* @author J.P. Tosca
* Sets a default template {@link Template} for a {@link Dataverse}.
*/
@RequiredPermissions(Permission.EditDataverse)
public class SetDefaultTemplateCommand extends AbstractCommand<Template> {

private final Template template;
private final Dataverse dataverse;

public SetDefaultTemplateCommand(Template template, DataverseRequest request, Dataverse dataverse) {
super(request, dataverse);
this.template = template;
this.dataverse = dataverse;
}

@Override
public Template execute(CommandContext ctxt) throws CommandException {
dataverse.setDefaultTemplate(template);
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

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

The command modifies the dataverse but doesn't persist the changes to the database. After calling dataverse.setDefaultTemplate(template), you should merge the dataverse entity using ctxt.em().merge(dataverse) to ensure the changes are persisted. See similar commands like CreateTemplateCommand (line 55) for reference.

Suggested change
dataverse.setDefaultTemplate(template);
dataverse.setDefaultTemplate(template);
ctxt.em().merge(dataverse);

Copilot uses AI. Check for mistakes.
return template;
}

}
2 changes: 2 additions & 0 deletions src/main/java/propertyFiles/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,8 @@ dataverse.update.featuredItems.error.invalidType=Unknown 'type' must be one of {
dataverse.update.featuredItems.error.typeAndDvObjectMismatch=The 'type' passed does not match the dvObject type.
dataverse.delete.featuredItems.success=All featured items of this Dataverse have been successfully deleted.
dataverse.createTemplate.error.jsonParseMetadataFields=Error parsing the POSTed template dataset fields: {0}
dataverse.setDefaultTemplate.success=The default dataset template has been successfully set for this dataverse.
dataverse.removeDefaultTemplate.success=The default dataset template has been successfully removed from this dataverse.
# rolesAndPermissionsFragment.xhtml

# advanced.xhtml
Expand Down
Loading