From 5c7e7625c252c1a455342387a160857485a4302f Mon Sep 17 00:00:00 2001 From: "Balazs E. Pataki" Date: Tue, 15 Sep 2026 07:56:43 +0200 Subject: [PATCH] Add explicit OpenAPI schemas for Response endpoints Document opaque Response endpoints with explicit JSON object and string response schemas so SmallRye emits valid OpenAPI types. This removes 86 oas-missing-type findings and raises Vacuum quality from 89 to 98. No Java return signatures or runtime behavior changed. --- .../edu/harvard/iq/dataverse/api/Access.java | 7 +- .../edu/harvard/iq/dataverse/api/Admin.java | 15 ++++ .../iq/dataverse/api/DatasetFields.java | 7 ++ .../harvard/iq/dataverse/api/Datasets.java | 73 +++++++++++++++++-- .../harvard/iq/dataverse/api/Dataverses.java | 56 ++++++++++++++ .../edu/harvard/iq/dataverse/api/Files.java | 15 +++- .../iq/dataverse/api/LocalContexts.java | 10 +++ .../harvard/iq/dataverse/api/Metadata.java | 20 +++++ .../iq/dataverse/api/MetadataBlocks.java | 10 +++ .../edu/harvard/iq/dataverse/api/Metrics.java | 67 +++++++++++++++++ .../edu/harvard/iq/dataverse/api/Pids.java | 23 ++++++ .../edu/harvard/iq/dataverse/api/SiteMap.java | 7 ++ .../edu/harvard/iq/dataverse/api/Users.java | 15 ++++ .../api/batchjob/BatchJobResource.java | 16 ++++ .../api/batchjob/FileRecordJobResource.java | 8 ++ .../iq/dataverse/mydata/DataRetrieverAPI.java | 8 ++ 16 files changed, 350 insertions(+), 7 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Access.java b/src/main/java/edu/harvard/iq/dataverse/api/Access.java index cdb27fd5f21..1510c8d2cf0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Access.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Access.java @@ -450,6 +450,9 @@ public Response datafile(@Context ContainerRequestContext crc, @Produces({"application/json"}) @Operation(summary = "Submit guestbook response for a data file", description = "Records the supplied guestbook response and returns access details for a data file download.") + @APIResponse(responseCode = "200", description = "Data-file access details.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response datafileWithGuestbookResponse(@Context ContainerRequestContext crc, @Parameter(description = "Data file id, persistent identifier, or path-style file reference.", required = true) @PathParam("fileId") String fileId, @@ -1656,7 +1659,9 @@ private String getWebappImageResource(String imageName) { description = "Saves an auxiliary file") @APIResponses(value = { @APIResponse(responseCode = "200", - description = "File saved response"), + description = "File saved response", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))), @APIResponse(responseCode = "403", description = "User not authorized to edit the dataset."), @APIResponse(responseCode = "400", diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index e30be924903..c8b641b0488 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -134,6 +134,7 @@ import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.StreamingOutput; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Content; import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; @@ -504,6 +505,9 @@ public Response enableAuthenticationProvider_deprecated(@Parameter(description = @Produces("application/json") @Operation(summary = "Switch authentication provider enabled state", description = "Enables or disables a registered authentication provider.") + @APIResponse(responseCode = "200", description = "Authentication provider state updated.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response enableAuthenticationProvider(@Parameter(description = "Authentication provider id.", required = true) @PathParam("id") String id, @RequestBody(description = "Boolean value indicating whether the provider should be enabled.") @@ -730,6 +734,9 @@ public Response listAuthenticatedUsers(@Context ContainerRequestContext crc) { @Produces({ "application/json" }) @Operation(summary = "Search authenticated users", description = "Searches authenticated users for the dashboard user list and returns paged JSON results.") + @APIResponse(responseCode = "200", description = "Paged authenticated user results.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response filterAuthenticatedUsers( @Context ContainerRequestContext crc, @Parameter(description = "Search text matched against authenticated users.") @@ -1327,6 +1334,10 @@ public Response setSuperuserStatus(@Parameter(description = "Authenticated user @Produces({"application/json"}) @Operation(summary = "Validate all datasets", description = "Streams validation results for every local dataset.") + @APIResponse(responseCode = "200", description = "Streaming dataset validation results.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT, + description = "Validation results grouped under a datasets array."))) public Response validateAllDatasets(@Parameter(description = "Whether to include variable-level validation details.") @QueryParam("variables") boolean includeVariables) { @@ -1473,6 +1484,10 @@ public Response validateDataset(@Parameter(description = "Dataset id or persiste @Produces({"application/json"}) @Operation(summary = "Validate files in one dataset", description = "Streams checksum validation results for all data files in a dataset.") + @APIResponse(responseCode = "200", description = "Streaming data-file validation results.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT, + description = "Checksum validation results grouped under a dataFiles array."))) public Response validateDatasetDatafiles(@Parameter(description = "Dataset id or persistent identifier.", required = true) @PathParam("id") String id) { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/DatasetFields.java b/src/main/java/edu/harvard/iq/dataverse/api/DatasetFields.java index 8aad30f34f3..3fb0b5cb4d0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/DatasetFields.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/DatasetFields.java @@ -8,6 +8,10 @@ import java.util.List; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import static edu.harvard.iq.dataverse.util.json.JsonPrinter.jsonDatasetFieldTypes; @@ -27,6 +31,9 @@ public class DatasetFields extends AbstractApiBean { @Path("facetables") @Operation(summary = "Lists facetable dataset fields", description = "Lists all facetable dataset fields defined in the installation.") + @APIResponse(responseCode = "200", description = "Facetable dataset fields.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response listAllFacetableDatasetFields() { List datasetFieldTypes = datasetFieldService.findAllFacetableFieldTypes(); return ok(jsonDatasetFieldTypes(datasetFieldTypes)); diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index 1b549b10a6b..2a2a5b4eb86 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -79,7 +79,9 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.logging.log4j.util.Strings; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @@ -251,6 +253,14 @@ public Response getDataset(@Context ContainerRequestContext crc, @Produces({"application/xml", "application/json", "application/html", "application/ld+json", "*/*" }) @Operation(summary = "Export dataset metadata", description = "Exports dataset metadata by persistent id using the requested version and exporter.") + @APIResponse(responseCode = "200", description = "Exported dataset metadata.", + content = { + @Content(mediaType = "application/xml", schema = @Schema(type = SchemaType.STRING)), + @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "application/html", schema = @Schema(type = SchemaType.STRING)), + @Content(mediaType = "application/ld+json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "*/*", schema = @Schema(type = SchemaType.STRING)) + }) public Response exportDataset(@Context ContainerRequestContext crc, @Parameter(description = "Persistent identifier.") @QueryParam("persistentId") String persistentId, @Parameter(description = "Dataset version selector.") @QueryParam("version") String versionId, @Parameter(description = "Exporter option.") @QueryParam("exporter") String exporter, @Context UriInfo uriInfo, @Context HttpHeaders headers, @Context HttpServletResponse response) { @@ -1624,6 +1634,9 @@ public Response moveDataset(@Context ContainerRequestContext crc, @Parameter(des @Operation(summary = "Embargoes dataset files", description = "Applies embargo settings to the specified dataset files after checking dataset edit permissions.") @RequestBody(description = "JSON payload identifying dataset files and embargo settings to apply.") + @APIResponse(responseCode = "200", description = "Dataset file embargo settings applied.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response createFileEmbargo(@Context ContainerRequestContext crc, @Parameter(description = "Resource id or persistent identifier.") @PathParam("id") String id, @RequestBody(description = "JSON payload identifying dataset files and embargo settings to apply.") String jsonBody){ @@ -1801,6 +1814,9 @@ public Response createFileEmbargo(@Context ContainerRequestContext crc, @Paramet @Operation(summary = "Removes file embargoes", description = "Removes embargoes from the specified dataset files after checking dataset edit permissions.") @RequestBody(description = "JSON payload identifying the dataset files whose embargoes should be removed.") + @APIResponse(responseCode = "200", description = "Dataset file embargoes removed.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response removeFileEmbargo(@Context ContainerRequestContext crc, @Parameter(description = "Resource id or persistent identifier.") @PathParam("id") String id, @RequestBody(description = "JSON payload identifying the dataset files whose embargoes should be removed.") String jsonBody){ @@ -2635,7 +2651,9 @@ public Response setDataFileAsThumbnail(@Context ContainerRequestContext crc, @Pa @Operation(summary = "Uploads a logo for a dataset", description = "Uploads a logo for a dataset") @APIResponse(responseCode = "200", - description = "Dataset logo uploaded successfully") + description = "Dataset logo uploaded successfully", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) @Tag(name = "uploadDatasetLogo", description = "Uploads a logo for a dataset") @RequestBody(description = "Multipart dataset logo upload containing the image file.", @@ -2906,6 +2924,9 @@ public Response getAvailableFileCategories(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Returns dataset curation status", description = "Returns the current or historical curation status for a dataset when the requester may view it.") + @APIResponse(responseCode = "200", description = "Dataset curation status.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response getCurationStatus(@Context ContainerRequestContext crc, @Parameter(description = "Resource id or persistent identifier.") @PathParam("id") String idSupplied, @Parameter(description = "Whether historical records are included.") @QueryParam("includeHistory") boolean includeHistory) { @@ -3233,7 +3254,9 @@ public Response completeMPUpload(@Context ContainerRequestContext crc, @Operation(summary = "Uploads a file for a dataset", description = "Uploads a file for a dataset") @APIResponse(responseCode = "200", - description = "File uploaded successfully to dataset") + description = "File uploaded successfully to dataset", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) @Tag(name = "addFileToDataset", description = "Uploads a file for a dataset") @RequestBody(description = "Multipart request containing one uploaded file and JSON metadata for the dataset.", @@ -4229,6 +4252,9 @@ public Response getAllowedCurationLabels(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Returns dataset timestamps", description = "Returns creation, publication, export, index, and update timestamps visible to the requester for a dataset.") + @APIResponse(responseCode = "200", description = "Dataset timestamps.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response getTimestamps(@Context ContainerRequestContext crc, @Parameter(description = "Dataset id or persistent identifier.") @PathParam("identifier") String id) { Dataset dataset = null; @@ -4346,6 +4372,9 @@ public Response getTimestamps(@Context ContainerRequestContext crc, @Parameter(d @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Returns Globus upload parameters", description = "Returns signed parameters and allowed callback URLs for a Globus upload or reference workflow for a dataset.") + @APIResponse(responseCode = "200", description = "Globus upload parameters.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response getGlobusUploadParams(@Context ContainerRequestContext crc, @Parameter(description = "Resource id or persistent identifier.") @PathParam("id") String datasetId, @Parameter(description = "Locale for localized Globus metadata.") @QueryParam(value = "locale") String locale) { // ------------------------------------- @@ -4463,6 +4492,9 @@ public Response getGlobusUploadParams(@Context ContainerRequestContext crc, @Par @Operation(summary = "Requests Globus upload paths", description = "Creates upload path assignments and permissions for a Globus user to upload files to a dataset.") @RequestBody(description = "Globus upload request with the transfer principal and number of files.") + @APIResponse(responseCode = "200", description = "Globus upload paths created.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response requestGlobusUpload(@Context ContainerRequestContext crc, @Parameter(description = "Resource id or persistent identifier.") @PathParam("id") String datasetId, @RequestBody(description = "Globus upload request with the transfer principal and number of files.") String jsonBody) throws IOException, ExecutionException, InterruptedException { @@ -4559,7 +4591,9 @@ public Response requestGlobusUpload(@Context ContainerRequestContext crc, @Param @Operation(summary = "Uploads a Globus file for a dataset", description = "Uploads a Globus file for a dataset") @APIResponse(responseCode = "200", - description = "Globus file uploaded successfully to dataset") + description = "Globus file uploaded successfully to dataset", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) @Tag(name = "addGlobusFilesToDataset", description = "Uploads a Globus file for a dataset") @RequestBody(description = "Multipart request containing Globus file metadata and transfer task information.", @@ -4685,6 +4719,9 @@ public Response addGlobusFilesToDataset(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Returns Globus download parameters", description = "Returns signed parameters and allowed callback URLs for a Globus download workflow for a dataset.") + @APIResponse(responseCode = "200", description = "Globus download parameters.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response getGlobusDownloadParams(@Context ContainerRequestContext crc, @Parameter(description = "Resource id or persistent identifier.") @PathParam("id") String datasetId, @Parameter(description = "Locale for localized Globus metadata.") @QueryParam(value = "locale") String locale, @Parameter(description = "Globus download request id.") @QueryParam(value = "downloadId") String downloadId) { // ------------------------------------- @@ -4787,6 +4824,9 @@ public Response getGlobusDownloadParams(@Context ContainerRequestContext crc, @P @Operation(summary = "Requests a Globus download", description = "Creates temporary Globus download permissions and returns endpoint path information for dataset files.") @RequestBody(description = "Globus download request with transfer principal and optional file id list.") + @APIResponse(responseCode = "200", description = "Globus download paths created.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response requestGlobusDownload(@Context ContainerRequestContext crc, @Parameter(description = "Resource id or persistent identifier.") @PathParam("id") String datasetId, @Parameter(description = "Globus download request id.") @QueryParam(value = "downloadId") String downloadId, @RequestBody(description = "Globus download request with transfer principal and optional file id list.") @@ -4993,7 +5033,9 @@ public Response monitorGlobusDownload(@Context ContainerRequestContext crc, @Par @Operation(summary = "Uploads a set of files to a dataset", description = "Uploads a set of files to a dataset") @APIResponse(responseCode = "200", - description = "Files uploaded successfully to dataset") + description = "Files uploaded successfully to dataset", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) @Tag(name = "addFilesToDataset", description = "Uploads a set of files to a dataset") @RequestBody(description = "Multipart request containing file content and JSON metadata for files to add.", @@ -5069,7 +5111,9 @@ public Response addFilesToDataset(@Context ContainerRequestContext crc, @Paramet @Operation(summary = "Replace a set of files to a dataset", description = "Replace a set of files to a dataset") @APIResponse(responseCode = "200", - description = "Files replaced successfully to dataset") + description = "Files replaced successfully to dataset", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) @Tag(name = "replaceFilesInDataset", description = "Replace a set of files to a dataset") @RequestBody(description = "Multipart request containing replacement file content and JSON metadata.", @@ -5389,6 +5433,9 @@ public Response getCurationStates(@Context ContainerRequestContext crc, @Path("/{id}/{version}/archivalStatus") @Operation(summary = "Returns archival status for a dataset version", description = "Returns stored archival status information for a dataset version when the requester is a superuser.") + @APIResponse(responseCode = "200", description = "Dataset version archival status.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response getDatasetVersionArchivalStatus(@Context ContainerRequestContext crc, @Parameter(description = "Resource id or persistent identifier.") @PathParam("id") String datasetId, @Parameter(description = "Dataset version selector.") @PathParam("version") String versionNumber, @@ -5483,6 +5530,9 @@ public Response setDatasetVersionArchivalStatus(@Context ContainerRequestContext @Path("/{id}/{version}/archivalStatus") @Operation(summary = "Deletes archival status for a dataset version", description = "Removes stored archival status information from a dataset version when the requester is a superuser.") + @APIResponse(responseCode = "200", description = "Dataset version archival status deleted.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response deleteDatasetVersionArchivalStatus(@Context ContainerRequestContext crc, @Parameter(description = "Resource id or persistent identifier.") @PathParam("id") String datasetId, @Parameter(description = "Dataset version selector.") @PathParam("version") String versionNumber, @@ -6692,6 +6742,11 @@ public Response deleteVersionNote(@Context ContainerRequestContext crc, @Produces({ MediaType.APPLICATION_JSON, "text/csv" }) @Operation(summary = "Read dataset role assignment history", description = "Returns dataset role assignment history as JSON or CSV.") + @APIResponse(responseCode = "200", description = "Dataset role assignment history.", + content = { + @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) + }) public Response getRoleAssignmentHistory(@Context ContainerRequestContext crc, @Parameter(description = "Dataset id or persistent identifier.", required = true) @PathParam("identifier") String id, @@ -6712,6 +6767,11 @@ public Response getRoleAssignmentHistory(@Context ContainerRequestContext crc, @Produces({ MediaType.APPLICATION_JSON, "text/csv" }) @Operation(summary = "Read file role assignment history", description = "Returns file-level role assignment history for a dataset as JSON or CSV.") + @APIResponse(responseCode = "200", description = "File role assignment history.", + content = { + @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) + }) public Response getFilesRoleAssignmentHistory(@Context ContainerRequestContext crc, @Parameter(description = "Dataset id or persistent identifier.", required = true) @PathParam("identifier") String id, @@ -6762,6 +6822,9 @@ public Response updateLicense(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Returns dataset reviews", description = "Returns review metadata stored for a dataset.") + @APIResponse(responseCode = "200", description = "Dataset reviews.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response getReviews(@Context ContainerRequestContext crc, @Parameter(description = "Dataset id or persistent identifier.", required = true) @PathParam("identifier") String id) { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java index ee45981162a..abf998efb6a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java @@ -78,8 +78,12 @@ import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import javax.xml.stream.XMLStreamException; @@ -385,6 +389,10 @@ public Response validateDatasetJson(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Read dataset schema for a dataverse", description = "Returns the dataset JSON schema generated for the selected dataverse.") + @APIResponse(responseCode = "200", description = "Dataset JSON schema.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT, + description = "JSON Schema document for datasets in the selected dataverse."))) public Response getDatasetSchema(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String idtf) { @@ -1003,6 +1011,9 @@ public Response listMetadataBlocks(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Assign metadata blocks to a dataverse", description = "Replaces the metadata blocks configured directly on a dataverse.") + @APIResponse(responseCode = "200", description = "Metadata blocks assigned.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response setMetadataBlocks(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String dvIdtf, @@ -1038,6 +1049,9 @@ public Response setMetadataBlocks(@Context ContainerRequestContext crc, @Path("{identifier}/metadatablocks/:isRoot") @Operation(summary = "Read metadata-block root status through legacy route", description = "Returns whether a dataverse is a metadata-block root using the legacy route.") + @APIResponse(responseCode = "200", description = "Metadata-block root status.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response getMetadataRoot_legacy(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String dvIdtf) { @@ -1050,6 +1064,9 @@ public Response getMetadataRoot_legacy(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Read metadata-block root status", description = "Returns whether a dataverse is a metadata-block root.") + @APIResponse(responseCode = "200", description = "Metadata-block root status.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response getMetadataRoot(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String dvIdtf) { @@ -1072,6 +1089,9 @@ public Response getMetadataRoot(@Context ContainerRequestContext crc, @Consumes(MediaType.WILDCARD) @Operation(summary = "Set metadata-block root status through legacy route", description = "Changes whether a dataverse is a metadata-block root using the legacy route.") + @APIResponse(responseCode = "200", description = "Metadata-block root status updated.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) @RequestBody(description = "Boolean text indicating whether the dataverse is a metadata-block root.") public Response setMetadataRoot_legacy(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @@ -1088,6 +1108,9 @@ public Response setMetadataRoot_legacy(@Context ContainerRequestContext crc, @Consumes(MediaType.WILDCARD) @Operation(summary = "Assign metadata-block root status", description = "Changes whether a dataverse is a metadata-block root.") + @APIResponse(responseCode = "200", description = "Metadata-block root status updated.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) @RequestBody(description = "Boolean text indicating whether the dataverse is a metadata-block root.") public Response setMetadataRoot(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @@ -1268,6 +1291,9 @@ public Response deleteFeaturedCollections(@Context ContainerRequestContext crc, */ @Operation(summary = "Assign dataverse facets", description = "Replaces the dataset field facets configured directly on a dataverse.") + @APIResponse(responseCode = "200", description = "Dataverse facets assigned.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response setFacets(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String dvIdtf, @@ -1298,6 +1324,10 @@ public Response setFacets(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Read metadata block facets", description = "Returns metadata block facet settings for a dataverse.") + @APIResponse(responseCode = "200", description = "Metadata block facets.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT, + description = "Dataverse metadata block facet settings."))) public Response listMetadataBlockFacets(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String dvIdtf) { @@ -1323,6 +1353,9 @@ public Response listMetadataBlockFacets(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Assign metadata block facets", description = "Replaces metadata block facets on a dataverse that is a metadata-block-facet root.") + @APIResponse(responseCode = "200", description = "Metadata block facets assigned.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response setMetadataBlockFacets(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String dvIdtf, @@ -1363,6 +1396,9 @@ public Response setMetadataBlockFacets(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Assign metadata block facet root status", description = "Changes whether a dataverse is a metadata-block-facet root.") + @APIResponse(responseCode = "200", description = "Metadata block facet root status updated.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) @RequestBody(description = "Boolean text indicating whether the dataverse is a metadata-block-facet root.") public Response updateMetadataBlockFacetsRoot(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @@ -2042,6 +2078,9 @@ public Response linkDataverse(@Context ContainerRequestContext crc, @Path("{identifier}/{type}/linkingDataverses") @Operation(summary = "Search dataverses for linking", description = "Lists dataverses that can be linked to the selected dataverse object, optionally filtered by search text and existing link status.") + @APIResponse(responseCode = "200", description = "Linkable dataverses.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response getLinkingDataverseList(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse object id or persistent identifier.", required = true) @PathParam("identifier") String dvIdtf, @@ -2589,6 +2628,11 @@ public Response deleteTemplate(@Context ContainerRequestContext crc, @Produces({ MediaType.APPLICATION_JSON, "text/csv" }) @Operation(summary = "Read dataverse role assignment history", description = "Returns dataverse role assignment history as JSON or CSV.") + @APIResponse(responseCode = "200", description = "Dataverse role assignment history.", + content = { + @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) + }) public Response getRoleAssignmentHistory(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String id, @@ -2711,6 +2755,9 @@ public Response listStorageDrivers(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Lists locally FAIR role assignees", description = "Lists role assignee identifiers configured for locally FAIR metadata access in a dataverse.") + @APIResponse(responseCode = "200", description = "Locally FAIR role assignees.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response listLocallyFairRoleAssignees(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String dvIdtf) { @@ -2738,6 +2785,9 @@ public Response listLocallyFairRoleAssignees(@Context ContainerRequestContext cr @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Replaces locally FAIR role assignees", description = "Replaces the full locally FAIR role assignee identifier set for a dataverse and reindexes the dataverse.") + @APIResponse(responseCode = "200", description = "Locally FAIR role assignees replaced.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) @RequestBody(description = "JSON array of role assignee identifiers to configure for locally FAIR metadata access.") public Response setLocallyFairRoleAssignees(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @@ -2768,6 +2818,9 @@ public Response setLocallyFairRoleAssignees(@Context ContainerRequestContext crc @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Adds a locally FAIR role assignee", description = "Adds one role assignee identifier to the locally FAIR metadata access set for a dataverse and reindexes the dataverse.") + @APIResponse(responseCode = "200", description = "Locally FAIR role assignee added.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response addLocallyFairRoleAssignee(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String dvIdtf, @@ -2800,6 +2853,9 @@ public Response addLocallyFairRoleAssignee(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Removes a locally FAIR role assignee", description = "Removes one role assignee identifier from the locally FAIR metadata access set for a dataverse and reindexes the dataverse.") + @APIResponse(responseCode = "200", description = "Locally FAIR role assignee removed.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response deleteLocallyFairRoleAssignee(@Context ContainerRequestContext crc, @Parameter(description = "Dataverse alias, id, or persistent identifier.", required = true) @PathParam("identifier") String dvIdtf, diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Files.java b/src/main/java/edu/harvard/iq/dataverse/api/Files.java index 458faf790ec..35b908fc6bc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Files.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Files.java @@ -71,7 +71,9 @@ import org.apache.commons.lang3.StringUtils; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @@ -228,7 +230,9 @@ public Response restrictFileInDataset(@Context ContainerRequestContext crc, @Operation(summary = "Replace a file on a dataset", description = "Replace a file to a dataset") @APIResponse(responseCode = "200", - description = "File replaced successfully on the dataset") + description = "File replaced successfully on the dataset", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) @Tag(name = "replaceFilesInDataset", description = "Replace a file to a dataset") @RequestBody(description = "Multipart request containing replacement file content and JSON replacement metadata.", @@ -1143,6 +1147,9 @@ public Response getFileDataTables(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Apply category labels to file metadata", description = "Adds or replaces category labels on the selected file metadata record.") + @APIResponse(responseCode = "200", description = "File categories updated.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response setFileCategories(@Context ContainerRequestContext crc, @Parameter(description = "Data file id or persistent identifier.", required = true) @PathParam("id") String dataFileId, @@ -1178,6 +1185,9 @@ public Response setFileCategories(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Apply tabular tags to a file", description = "Adds or replaces tabular data tags on a tabular data file.") + @APIResponse(responseCode = "200", description = "File tabular tags updated.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response setFileTabularTags(@Context ContainerRequestContext crc, @Parameter(description = "Data file id or persistent identifier.", required = true) @PathParam("id") String dataFileId, @@ -1273,6 +1283,9 @@ public Response getFileCitationByVersion(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Compare file versions", description = "Reports metadata differences across versions for a data file.") + @APIResponse(responseCode = "200", description = "File version differences.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response getFileVersionsList(@Context ContainerRequestContext crc, @Parameter(description = "Data file id or persistent identifier.", required = true) @PathParam("id") String fileIdOrPersistentId, diff --git a/src/main/java/edu/harvard/iq/dataverse/api/LocalContexts.java b/src/main/java/edu/harvard/iq/dataverse/api/LocalContexts.java index 5f614ba7d9c..f408e33e349 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/LocalContexts.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/LocalContexts.java @@ -30,7 +30,11 @@ import jakarta.ws.rs.core.Response; import jakarta.ws.rs.container.ContainerRequestContext; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; @Path("localcontexts") @@ -54,6 +58,9 @@ public class LocalContexts extends AbstractApiBean { @AuthRequired @Operation(summary = "Finds Local Contexts projects for a dataset", description = "Queries the configured Local Contexts service by dataset DOI and returns matching project information when the requester is allowed to inspect the dataset.") + @APIResponse(responseCode = "200", description = "Local Contexts project information.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response getDatasetLocalContexts(@Context ContainerRequestContext crc, @Parameter(description = "Dataset id or persistent identifier whose DOI is sent to Local Contexts.", required = true) @PathParam("id") String id) { @@ -122,6 +129,9 @@ public Response getDatasetLocalContexts(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Returns a Local Contexts project", description = "Returns a Local Contexts project only when the project response includes a DOI matching the specified dataset.") + @APIResponse(responseCode = "200", description = "Local Contexts project.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response searchLocalContexts( @Parameter(description = "Dataset id or persistent identifier used to validate the Local Contexts project DOI.", required = true) @PathParam("id") String datasetId, diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Metadata.java b/src/main/java/edu/harvard/iq/dataverse/api/Metadata.java index 7a820678489..8070c0286ae 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Metadata.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Metadata.java @@ -24,7 +24,11 @@ import java.util.List; import java.util.Set; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; /** @@ -57,6 +61,13 @@ public class Metadata extends AbstractApiBean { @Produces("application/json") @Operation(summary = "Starts metadata export jobs", description = "Starts background exports for published local datasets that have not been exported since their last publication.") + @APIResponse(responseCode = "200", description = "This endpoint responds with 202 when the export is accepted.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) + @APIResponse(responseCode = "202", description = "Metadata export jobs accepted.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT, + description = "Indicates that the background export is in progress."))) public Response exportAll() { datasetService.exportAllAsync(); return this.accepted(); @@ -69,9 +80,17 @@ public Response exportAll() { @Produces("application/json") @Operation(summary = "Starts metadata re-export jobs", description = "Starts background re-export jobs for published local datasets, optionally limited to datasets older than a supplied date.") + @APIResponse(responseCode = "200", description = "This endpoint responds with 202 when the re-export is accepted.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) + @APIResponse(responseCode = "202", description = "Metadata re-export jobs accepted.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT, + description = "Indicates that the background re-export is in progress."))) public Response reExportAll( @Parameter(description = "Optional cutoff date in YYYY-MM-DD format for selecting datasets to re-export.") @QueryParam(value = "olderThan") String olderThan, + @Parameter(description = "Comma-separated metadata export formats to re-export; omitted to use all configured formats.") @QueryParam("formats") String formats) { Date reExportDate = null; if (olderThan != null && !olderThan.isEmpty()) { @@ -99,6 +118,7 @@ public Response reExportAll( public Response exportDatasetByPersistentId( @Parameter(description = "Dataset id or persistent identifier to re-export.", required = true) @PathParam("id") String id, + @Parameter(description = "Comma-separated metadata export formats to re-export; omitted to use all configured formats.") @QueryParam("formats") String formats) { try { Dataset dataset = findDatasetOrDie(id); diff --git a/src/main/java/edu/harvard/iq/dataverse/api/MetadataBlocks.java b/src/main/java/edu/harvard/iq/dataverse/api/MetadataBlocks.java index 8bf208c6de5..b33f6161629 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/MetadataBlocks.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/MetadataBlocks.java @@ -4,7 +4,11 @@ import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import java.util.List; @@ -24,6 +28,9 @@ public class MetadataBlocks extends AbstractApiBean { @GET @Operation(summary = "Lists metadata blocks", description = "Returns metadata blocks as JSON, optionally limited to blocks displayed during dataset creation and optionally including dataset field types.") + @APIResponse(responseCode = "200", description = "Metadata blocks.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response listMetadataBlocks( @Parameter(description = "Limit results to metadata blocks displayed during dataset creation.") @QueryParam("onlyDisplayedOnCreate") boolean onlyDisplayedOnCreate, @@ -37,6 +44,9 @@ public Response listMetadataBlocks( @GET @Operation(summary = "Returns a metadata block", description = "Returns the metadata block identified by id, name, or display name.") + @APIResponse(responseCode = "200", description = "Metadata block.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response getMetadataBlock( @Parameter(description = "Metadata block id, name, or display name.", required = true) @PathParam("identifier") String idtf) { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Metrics.java b/src/main/java/edu/harvard/iq/dataverse/api/Metrics.java index 5cece335f5c..35cc510a75e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Metrics.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Metrics.java @@ -29,7 +29,11 @@ import jakarta.ws.rs.core.UriInfo; import jakarta.ws.rs.core.Variant; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; /** @@ -64,6 +68,9 @@ public Response getDataversesAllTime(@Context UriInfo uriInfo, @Produces("text/csv, application/json") @Operation(summary = "Calculates monthly dataverse counts", description = "Calculates a monthly time series of released dataverse counts as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getDataversesTimeSeries(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -160,6 +167,9 @@ public Response getDataversesPastDays(@Context UriInfo uriInfo, @Produces("text/csv, application/json") @Operation(summary = "Calculates dataverse counts by category", description = "Calculates released dataverse counts grouped by dataverse category as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getDataversesByCategory(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -191,6 +201,9 @@ public Response getDataversesByCategory(@Context Request req, @Context UriInfo u @Produces("text/csv, application/json") @Operation(summary = "Calculates dataverse counts by subject", description = "Calculates released dataverse counts grouped by subject as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getDataversesBySubject(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -237,6 +250,9 @@ public Response getDatasetsAllTime(@Context UriInfo uriInfo, @Produces("text/csv, application/json") @Operation(summary = "Calculates monthly dataset counts", description = "Calculates a monthly time series of released dataset counts as JSON or CSV, optionally filtered by storage location and parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getDatasetsTimeSeriest(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Storage location filter for the dataset metric.") @QueryParam("dataLocation") String dataLocation, @@ -342,6 +358,9 @@ public Response getDatasetsPastDays(@Context UriInfo uriInfo, @Produces("text/csv, application/json") @Operation(summary = "Calculates dataset counts by subject", description = "Calculates released dataset counts grouped by subject through the current month as JSON or CSV, optionally filtered by storage location and parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getDatasetsBySubject(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Storage location filter for the dataset metric.") @QueryParam("dataLocation") String dataLocation, @@ -355,6 +374,9 @@ public Response getDatasetsBySubject(@Context Request req, @Context UriInfo uriI @Produces("text/csv, application/json") @Operation(summary = "Calculates dataset counts by subject through a month", description = "Calculates released dataset counts grouped by subject through the specified month as JSON or CSV, optionally filtered by storage location and parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getDatasetsBySubjectToMonth(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Year and month cutoff for the metric, formatted as YYYYMM.", required = true) @PathParam("yyyymm") String yyyymm, @@ -403,6 +425,9 @@ public Response getFilesAllTime(@Context UriInfo uriInfo, @Produces("text/csv, application/json") @Operation(summary = "Calculates monthly file counts", description = "Calculates a monthly time series of released file counts as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getFilesTimeSeries(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -502,6 +527,9 @@ public Response getFilesPastDays(@Context UriInfo uriInfo, @Produces("text/csv, application/json") @Operation(summary = "Calculates monthly file counts by type", description = "Calculates a monthly time series of released file counts and sizes grouped by content type as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getFilesByTypeTimeSeries(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -532,6 +560,9 @@ public Response getFilesByTypeTimeSeries(@Context Request req, @Context UriInfo @Produces("text/csv, application/json") @Operation(summary = "Calculates file counts by type", description = "Calculates released file counts and sizes grouped by content type as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getFilesByType(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -575,6 +606,9 @@ public Response getDownloadsAllTime(@Context UriInfo uriInfo, @Produces("text/csv, application/json") @Operation(summary = "Calculates monthly download counts", description = "Calculates a monthly time series of file download counts as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getDownloadsTimeSeries(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -748,6 +782,9 @@ public Response getAccountsPastDays(@Context UriInfo uriInfo, @Produces("text/csv, application/json") @Operation(summary = "Calculates monthly account counts", description = "Calculates a monthly time series of user account counts as JSON or CSV.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getAccountsTimeSeries(@Context Request req, @Context UriInfo uriInfo) { try { @@ -793,6 +830,9 @@ public Response getMakeDataCountMetricCurrentMonth(@Context UriInfo uriInfo, @Produces("text/csv, application/json") @Operation(summary = "Calculates monthly Make Data Count metrics", description = "Calculates a monthly time series for the requested Make Data Count metric as JSON or CSV, optionally filtered by country and parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getMakeDataCountMetricTimeSeries(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Make Data Count metric name to return.", required = true) @PathParam("metric") String metricSupplied, @@ -889,6 +929,9 @@ public Response getMakeDataCountMetricToMonth(@Context UriInfo uriInfo, @Produces("text/csv, application/json") @Operation(summary = "Calculates file download counts", description = "Calculates file download counts by file through the current month as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getFileDownloadsAllTime(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -900,6 +943,9 @@ public Response getFileDownloadsAllTime(@Context Request req, @Context UriInfo u @Produces("text/csv, application/json") @Operation(summary = "Calculates file download counts through a month", description = "Calculates file download counts by file through the specified month as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getFileDownloadsToMonth(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Year and month cutoff for the metric, formatted as YYYYMM.", required = true) @PathParam("yyyymm") String yyyymm, @@ -934,6 +980,9 @@ public Response getFileDownloadsToMonth(@Context Request req, @Context UriInfo u @Produces("text/csv, application/json") @Operation(summary = "Calculates monthly file download counts", description = "Calculates a monthly time series of file download counts by file as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getFileDownloadsTimeSeries(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -964,6 +1013,9 @@ public Response getFileDownloadsTimeSeries(@Context Request req, @Context UriInf @Produces("text/csv, application/json") @Operation(summary = "Calculates unique dataset download counts", description = "Calculates unique dataset download counts through the current month as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getUniqueDownloadsAllTime(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -975,6 +1027,9 @@ public Response getUniqueDownloadsAllTime(@Context Request req, @Context UriInfo @Produces("text/csv, application/json") @Operation(summary = "Calculates monthly unique dataset download counts", description = "Calculates a monthly time series of unique dataset download counts as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getUniqueDownloadsTimeSeries(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -1005,6 +1060,9 @@ public Response getUniqueDownloadsTimeSeries(@Context Request req, @Context UriI @Produces("text/csv, application/json") @Operation(summary = "Calculates unique dataset download counts through a month", description = "Calculates unique dataset download counts through the specified month as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getUniqueDownloadsToMonth(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Year and month cutoff for the metric, formatted as YYYYMM.", required = true) @PathParam("yyyymm") String yyyymm, @@ -1039,6 +1097,9 @@ public Response getUniqueDownloadsToMonth(@Context Request req, @Context UriInfo @Produces("text/csv, application/json") @Operation(summary = "Calculates unique file download counts", description = "Calculates unique file download counts by file through the current month as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getUniqueFileDownloadsAllTime(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { @@ -1050,6 +1111,9 @@ public Response getUniqueFileDownloadsAllTime(@Context Request req, @Context Uri @Produces("text/csv, application/json") @Operation(summary = "Calculates unique file download counts through a month", description = "Calculates unique file download counts by file through the specified month as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getUniqueFileDownloadsToMonth(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Year and month cutoff for the metric, formatted as YYYYMM.", required = true) @PathParam("yyyymm") String yyyymm, @@ -1084,6 +1148,9 @@ public Response getUniqueFileDownloadsToMonth(@Context Request req, @Context Uri @Produces("text/csv, application/json") @Operation(summary = "Calculates monthly unique file download counts", description = "Calculates a monthly time series of unique file download counts by file as JSON or CSV, optionally scoped to a released parent dataverse.") + @APIResponse(responseCode = "200", description = "Metric results in JSON or CSV.", + content = { @Content(mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", schema = @Schema(type = SchemaType.STRING)) }) public Response getUniqueFileDownloadsTimeSeries(@Context Request req, @Context UriInfo uriInfo, @Parameter(description = "Alias of a released parent dataverse used to scope the metric.") @QueryParam("parentAlias") String parentAlias) { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Pids.java b/src/main/java/edu/harvard/iq/dataverse/api/Pids.java index db47de7bbed..9a96fde3c27 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Pids.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Pids.java @@ -32,7 +32,11 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; /** @@ -53,6 +57,9 @@ public class Pids extends AbstractApiBean { @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Returns PID provider metadata", description = "Queries configured DataCite metadata for the supplied persistent identifier when the requester is a superuser.") + @APIResponse(responseCode = "200", description = "PID provider metadata.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response getPid(@Context ContainerRequestContext crc, @Parameter(description = "Persistent identifier to query.") @QueryParam("persistentId") String persistentId) { @@ -84,6 +91,10 @@ public Response getPid(@Context ContainerRequestContext crc, @Path("unreserved") @Operation(summary = "Lists unreserved dataset PIDs", description = "Returns draft datasets whose persistent identifiers have not been reserved when the requester is a superuser.") + @APIResponse(responseCode = "200", description = "Unreserved dataset PIDs.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT, + description = "Contains the total in numUnreserved and the matching dataset records in count."))) public Response getUnreserved(@Context ContainerRequestContext crc, @Parameter(description = "Optional persistent identifier value accepted by the endpoint.") @QueryParam("persistentId") String persistentId) { @@ -118,6 +129,9 @@ public Response getUnreserved(@Context ContainerRequestContext crc, @Path("{id}/reserve") @Operation(summary = "Reserves a dataset PID", description = "Reserves the persistent identifier for the specified dataset.") + @APIResponse(responseCode = "200", description = "PID reserved.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response reservePid(@Context ContainerRequestContext crc, @Parameter(description = "Dataset id or persistent identifier whose PID is reserved.", required = true) @PathParam("id") String idSupplied) { @@ -136,6 +150,9 @@ public Response reservePid(@Context ContainerRequestContext crc, @Path("{id}/delete") @Operation(summary = "Deletes a draft dataset PID", description = "Deletes the persistent identifier for an unpublished dataset.") + @APIResponse(responseCode = "200", description = "Draft PID deleted.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response deletePid(@Context ContainerRequestContext crc, @Parameter(description = "Dataset id or persistent identifier whose PID is deleted.", required = true) @PathParam("id") String idSupplied) { @@ -160,6 +177,9 @@ public Response deletePid(@Context ContainerRequestContext crc, @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Lists PID providers", description = "Returns the configured persistent identifier providers.") + @APIResponse(responseCode = "200", description = "Configured PID providers.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response getPidProviders(@Context ContainerRequestContext crc) throws WrappedResponse { try { getRequestAuthenticatedUserOrDie(crc); @@ -177,6 +197,9 @@ public Response getPidProviders(@Context ContainerRequestContext crc) throws Wra @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Returns the provider for a PID", description = "Parses a persistent identifier and returns the managed provider id or reports that the PID belongs to an unmanaged provider.") + @APIResponse(responseCode = "200", description = "PID provider result.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response getPidProviderId(@Context ContainerRequestContext crc, @Parameter(description = "Persistent identifier whose provider is requested.", required = true) @PathParam("persistentId") String persistentId) throws WrappedResponse { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/SiteMap.java b/src/main/java/edu/harvard/iq/dataverse/api/SiteMap.java index 489260ec1b8..f9d57aec7f3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/SiteMap.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/SiteMap.java @@ -10,6 +10,10 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; @Stateless @@ -24,6 +28,9 @@ public class SiteMap extends AbstractApiBean { @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Starts a sitemap update", description = "Starts regeneration of the site map for all dataverses and datasets when no staged sitemap file is present.") + @APIResponse(responseCode = "200", description = "Sitemap update started.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT))) public Response updateSiteMap() { boolean stageFileExists = SiteMapUtil.stageFileExists(); if (stageFileExists) { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Users.java b/src/main/java/edu/harvard/iq/dataverse/api/Users.java index cec3a0cd7e0..a5b149b53d9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Users.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Users.java @@ -38,8 +38,12 @@ import jakarta.ws.rs.container.ContainerRequestContext; import jakarta.ws.rs.core.*; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; /** @@ -280,6 +284,14 @@ public Response getTraces(@Context ContainerRequestContext crc, @Produces("text/csv, application/json") @Operation(summary = "Returns a user trace element", description = "Returns one category of trace information for the specified authenticated user as JSON or CSV.") + @APIResponse(responseCode = "200", description = "User trace element.", + content = { + @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT)), + @Content(mediaType = "text/csv", + schema = @Schema(type = SchemaType.STRING, + description = "CSV representation of the selected trace element.")) + }) public Response getTracesElement(@Context ContainerRequestContext crc, @Context Request req, @Parameter(description = "Authenticated user identifier whose trace element is returned.", required = true) @PathParam("identifier") String identifier, @@ -319,6 +331,9 @@ public Response getTracesElement(@Context ContainerRequestContext crc, @Context @Produces("application/json") @Operation(summary = "Lists collections permitted for a user", description = "Returns collections where the specified user has the requested permission when the requester is that user or a superuser.") + @APIResponse(responseCode = "200", description = "Permitted collections.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT))) public Response getUserPermittedCollections(@Context ContainerRequestContext crc, @Context Request req, @Parameter(description = "Authenticated user identifier whose permitted collections are returned.", required = true) @PathParam("identifier") String identifier, diff --git a/src/main/java/edu/harvard/iq/dataverse/api/batchjob/BatchJobResource.java b/src/main/java/edu/harvard/iq/dataverse/api/batchjob/BatchJobResource.java index faf0e5041fc..5c894442032 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/batchjob/BatchJobResource.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/batchjob/BatchJobResource.java @@ -18,8 +18,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; @@ -37,6 +41,10 @@ public class BatchJobResource extends AbstractApiBean { @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Lists batch jobs", description = "Returns JSON containing the execution records for all known batch job instances.") + @APIResponse(responseCode = "200", description = "Batch job execution records.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT, + description = "Batch execution records grouped under a jobs array."))) public Response listBatchJobs() { try { final List executionEntities = new ArrayList<>(); @@ -63,6 +71,10 @@ public Response listBatchJobs() { @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Lists batch jobs by name", description = "Returns JSON containing execution records for batch job instances with the specified job name.") + @APIResponse(responseCode = "200", description = "Batch job execution records for the selected job name.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT, + description = "JSON object containing a jobs array of batch execution records."))) public Response listBatchJobsByName( @Parameter(description = "Batch job name used to select job instances.", required = true) @PathParam("jobName") String jobName) { @@ -89,6 +101,10 @@ public Response listBatchJobsByName( @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Returns a batch job execution", description = "Returns the execution record for the specified batch job execution id as JSON.") + @APIResponse(responseCode = "200", description = "Batch job execution record.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT, + description = "JSON object containing one batch execution record."))) public Response listBatchJobById( @Parameter(description = "Numeric batch job execution id.", required = true) @PathParam("jobId") String jobId) { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/batchjob/FileRecordJobResource.java b/src/main/java/edu/harvard/iq/dataverse/api/batchjob/FileRecordJobResource.java index 1b4141f858a..9b2144fe5c1 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/batchjob/FileRecordJobResource.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/batchjob/FileRecordJobResource.java @@ -23,7 +23,11 @@ import jakarta.json.Json; import jakarta.json.JsonObject; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; @Stateless @@ -46,6 +50,10 @@ public class FileRecordJobResource extends AbstractApiBean { @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Starts a file-system import job", description = "Starts a background job that imports files from a server-side upload folder into the specified dataset and returns the job execution id.") + @APIResponse(responseCode = "200", description = "File-system import job accepted.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.OBJECT, + description = "Contains the job message and executionId."))) public Response getFilesystemImport(@Context ContainerRequestContext crc, @Parameter(description = "Dataset id or persistent identifier that receives the imported files.", required = true) @PathParam("identifier") String identifier, diff --git a/src/main/java/edu/harvard/iq/dataverse/mydata/DataRetrieverAPI.java b/src/main/java/edu/harvard/iq/dataverse/mydata/DataRetrieverAPI.java index 1abfad90cb0..a26d0733e94 100644 --- a/src/main/java/edu/harvard/iq/dataverse/mydata/DataRetrieverAPI.java +++ b/src/main/java/edu/harvard/iq/dataverse/mydata/DataRetrieverAPI.java @@ -41,7 +41,11 @@ import jakarta.ws.rs.core.Response; import org.json.JSONObject; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; /** @@ -336,6 +340,10 @@ private JsonObjectBuilder myDataAsJson(String message, Pager pager, RoleTagRetri @Produces("application/json") @Operation(summary = "Lists collections for My Data", description = "Returns collections where the requester or selected user may add datasets.") + @APIResponse(responseCode = "200", description = "Permitted collections.", + content = @Content(mediaType = "application/json", + schema = @Schema(type = SchemaType.OBJECT, + description = "Permitted collections for the selected user."))) public Response retrieveMyCollectionList(@Context ContainerRequestContext crc, @Parameter(description = "User identifier filter.") @QueryParam("userIdentifier") String userIdentifier) { try { verifyAuth(crc, userIdentifier);