/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
package org.roda.wui.api.v1;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.xml.transform.TransformerException;
import org.apache.commons.lang3.StringUtils;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.roda.core.common.EntityResponse;
import org.roda.core.common.StreamResponse;
import org.roda.core.common.UserUtility;
import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.exceptions.AlreadyExistsException;
import org.roda.core.data.exceptions.AuthorizationDeniedException;
import org.roda.core.data.exceptions.GenericException;
import org.roda.core.data.exceptions.NotFoundException;
import org.roda.core.data.exceptions.RODAException;
import org.roda.core.data.exceptions.RequestNotValidException;
import org.roda.core.data.v2.common.Pair;
import org.roda.core.data.v2.index.IndexResult;
import org.roda.core.data.v2.index.filter.Filter;
import org.roda.core.data.v2.index.select.SelectedItemsList;
import org.roda.core.data.v2.index.sort.Sorter;
import org.roda.core.data.v2.index.sublist.Sublist;
import org.roda.core.data.v2.ip.TransferredResources;
import org.roda.core.data.v2.user.User;
import org.roda.wui.api.controllers.Browser;
import org.roda.wui.api.v1.utils.ApiResponseMessage;
import org.roda.wui.api.v1.utils.ApiUtils;
import org.roda.wui.api.v1.utils.ObjectResponse;
import org.roda.wui.common.I18nUtility;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
@Path(TransferredResource.ENDPOINT)
@Api(value = TransferredResource.SWAGGER_ENDPOINT)
public class TransferredResource {
public static final String ENDPOINT = "/v1/transfers";
public static final String SWAGGER_ENDPOINT = "v1 transfers";
@Context
private HttpServletRequest request;
@GET
@ApiOperation(value = "List resources", notes = "Get a list of resources.", response = TransferredResources.class, responseContainer = "List")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful response", response = TransferredResources.class, responseContainer = "List"),
@ApiResponse(code = 404, message = "Not found", response = ApiResponseMessage.class)})
public Response listTransferredResources(
@ApiParam(value = "Index of the first element to return", defaultValue = "0") @QueryParam(RodaConstants.API_QUERY_KEY_START) String start,
@ApiParam(value = "Maximum number of elements to return", defaultValue = "100") @QueryParam(RodaConstants.API_QUERY_KEY_LIMIT) String limit,
@ApiParam(value = "Choose format in which to get the resources", allowableValues = RodaConstants.API_LIST_MEDIA_TYPES, defaultValue = RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON) @QueryParam(RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT) String acceptFormat)
throws RODAException {
String mediaType = ApiUtils.getMediaType(acceptFormat, request);
// get user
User user = UserUtility.getApiUser(request);
// delegate action to controller
boolean justActive = false;
Pair<Integer, Integer> pagingParams = ApiUtils.processPagingParams(start, limit);
IndexResult<org.roda.core.data.v2.ip.TransferredResource> result = Browser.find(
org.roda.core.data.v2.ip.TransferredResource.class, Filter.NULL, Sorter.NONE,
new Sublist(pagingParams.getFirst(), pagingParams.getSecond()), null, user, justActive, new ArrayList<>());
return Response
.ok(ApiUtils.indexedResultToRODAObjectList(org.roda.core.data.v2.ip.TransferredResource.class, result), mediaType)
.build();
}
@GET
@Path("/{" + RodaConstants.API_PATH_PARAM_TRANSFERRED_RESOURCE_UUID + "}")
@ApiOperation(value = "Get resource", notes = "Get a resource.", response = org.roda.core.data.v2.ip.TransferredResource.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = org.roda.core.data.v2.ip.TransferredResource.class),
@ApiResponse(code = 404, message = "Not found", response = ApiResponseMessage.class)})
public Response getResource(
@ApiParam(value = "The resource id", required = false) @PathParam(RodaConstants.API_PATH_PARAM_TRANSFERRED_RESOURCE_UUID) String resourceId,
@ApiParam(value = "Choose format in which to get the resource", allowableValues = RodaConstants.API_GET_FILE_MEDIA_TYPES) @QueryParam(RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT) String acceptFormat)
throws AuthorizationDeniedException, NotFoundException, RequestNotValidException, GenericException {
String mediaType = ApiUtils.getMediaType(acceptFormat, request);
// get user
User user = UserUtility.getApiUser(request);
// delegate action to controller
EntityResponse response = Browser.retrieveTransferredResource(user, resourceId, acceptFormat);
if (response instanceof ObjectResponse) {
ObjectResponse<org.roda.core.data.v2.ip.TransferredResource> tr = (ObjectResponse<org.roda.core.data.v2.ip.TransferredResource>) response;
return Response.ok(tr.getObject(), mediaType).build();
} else {
return ApiUtils.okResponse((StreamResponse) response);
}
}
/*
* 20160909 hsilva: do not change form param strings ("upl")
*/
@POST
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@ApiOperation(value = "Create resource", notes = "Create a resource.", response = org.roda.core.data.v2.ip.TransferredResource.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = org.roda.core.data.v2.ip.TransferredResource.class),
@ApiResponse(code = 409, message = "Already exists", response = ApiResponseMessage.class)})
public Response createResource(
@ApiParam(value = "The id of the parent") @QueryParam(RodaConstants.TRANSFERRED_RESOURCE_PARENT_UUID) String parentUUID,
@ApiParam(value = "The name of the directory to create", required = false) @QueryParam(RodaConstants.TRANSFERRED_RESOURCE_DIRECTORY_NAME) String name,
@ApiParam(value = "Locale", required = false) @QueryParam(RodaConstants.LOCALE) String localeString,
@FormDataParam(RodaConstants.API_PARAM_UPLOAD) InputStream inputStream,
@FormDataParam(RodaConstants.API_PARAM_UPLOAD) FormDataContentDisposition fileDetail,
@ApiParam(value = "Commit after creation", defaultValue = "false", required = false) @QueryParam(RodaConstants.API_QUERY_PARAM_COMMIT) String commitString,
@ApiParam(value = "Choose format in which to get the resource", allowableValues = RodaConstants.API_POST_PUT_MEDIA_TYPES) @QueryParam(RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT) String acceptFormat)
throws RODAException {
String mediaType = ApiUtils.getMediaType(acceptFormat, request);
// get user
User user = UserUtility.getApiUser(request);
// delegate action to controller
try {
org.roda.core.data.v2.ip.TransferredResource transferredResource;
String fileName = fileDetail.getFileName();
boolean forceCommit = false;
if (StringUtils.isNotBlank(commitString)) {
forceCommit = Boolean.parseBoolean(commitString);
}
if (name == null) {
transferredResource = Browser.createTransferredResourceFile(user, parentUUID, fileName, inputStream,
forceCommit);
} else {
transferredResource = Browser.createTransferredResourcesFolder(user, parentUUID, name, forceCommit);
}
return Response.ok(transferredResource, mediaType).build();
} catch (AlreadyExistsException e) {
return Response.status(Status.CONFLICT).entity(new ApiResponseMessage(ApiResponseMessage.ERROR,
I18nUtility.getMessage("ui.upload.error.alreadyexists", e.getMessage(), localeString))).build();
}
}
@PUT
@ApiOperation(value = "Update resource", notes = "Update existing resources", response = org.roda.core.data.v2.ip.TransferredResource.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = org.roda.core.data.v2.ip.TransferredResource.class),
@ApiResponse(code = 404, message = "Not found", response = ApiResponseMessage.class)})
public Response updateTransferredResource(
@ApiParam(value = "The relative path of the resource") @QueryParam(RodaConstants.TRANSFERRED_RESOURCE_RELATIVEPATH) String relativePath,
@FormDataParam(RodaConstants.API_PARAM_UPLOAD) InputStream inputStream,
@FormDataParam(RodaConstants.API_PARAM_UPLOAD) FormDataContentDisposition fileDetail,
@ApiParam(value = "Choose format in which to get the response", allowableValues = RodaConstants.API_POST_PUT_MEDIA_TYPES) @QueryParam(RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT) String acceptFormat)
throws RODAException {
String mediaType = ApiUtils.getMediaType(acceptFormat, request);
// get user
User user = UserUtility.getApiUser(request);
// delegate action to controller
try {
Browser.updateTransferredResource(user, Optional.of(relativePath), inputStream, fileDetail.getFileName(), false);
return Response.ok(new ApiResponseMessage(ApiResponseMessage.OK, "Transferred resources updated"), mediaType)
.build();
} catch (IOException e) {
return ApiUtils.errorResponse(new TransformerException(e.getMessage()));
}
}
@DELETE
@Path("/{" + RodaConstants.API_PATH_PARAM_TRANSFERRED_RESOURCE_UUID + "}")
@ApiOperation(value = "Delete resource", notes = "Delete a resource.", response = Void.class)
@ApiResponses(value = {@ApiResponse(code = 204, message = "OK", response = Void.class),
@ApiResponse(code = 404, message = "Not found", response = ApiResponseMessage.class)})
public Response deleteResource(
@ApiParam(value = "The id of the resource", required = true) @PathParam(RodaConstants.API_PATH_PARAM_TRANSFERRED_RESOURCE_UUID) String path,
@ApiParam(value = "Choose format in which to get the response", allowableValues = RodaConstants.API_DELETE_MEDIA_TYPES) @QueryParam(RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT) String acceptFormat)
throws RODAException {
String mediaType = ApiUtils.getMediaType(acceptFormat, request);
// get user
User user = UserUtility.getApiUser(request);
// delegate action to controller
SelectedItemsList<org.roda.core.data.v2.ip.TransferredResource> selected = new SelectedItemsList<>(
Arrays.asList(path), org.roda.core.data.v2.ip.TransferredResource.class.getName());
Browser.deleteTransferredResources(user, selected);
return Response.ok(new ApiResponseMessage(ApiResponseMessage.OK, "Transferred resource deleted"), mediaType)
.build();
}
@DELETE
@ApiOperation(value = "Delete resources", notes = "Delete multiple resources.", response = Void.class)
@ApiResponses(value = {@ApiResponse(code = 204, message = "OK", response = Void.class),
@ApiResponse(code = 404, message = "Not found", response = ApiResponseMessage.class)})
public Response deleteMultipleResources(
@ApiParam(value = "The id of the resources", allowMultiple = true) @QueryParam("transferred_resource_ids") List<String> paths,
@ApiParam(value = "Choose format in which to get the response", allowableValues = RodaConstants.API_DELETE_MEDIA_TYPES) @QueryParam(RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT) String acceptFormat)
throws RODAException {
String mediaType = ApiUtils.getMediaType(acceptFormat, request);
// get user
User user = UserUtility.getApiUser(request);
// delegate action to controller
SelectedItemsList<org.roda.core.data.v2.ip.TransferredResource> selected = new SelectedItemsList<>(paths,
org.roda.core.data.v2.ip.TransferredResource.class.getName());
Browser.deleteTransferredResources(user, selected);
return Response.ok(new ApiResponseMessage(ApiResponseMessage.OK, "Transferred resources deleted"), mediaType)
.build();
}
@GET
@Path("/reindex")
@ApiOperation(value = "Reindex resource", notes = "Reindex resource.", response = Void.class)
@ApiResponses(value = {@ApiResponse(code = 204, message = "OK", response = Void.class),
@ApiResponse(code = 404, message = "Not found", response = ApiResponseMessage.class)})
public Response reindexResources(
@ApiParam(value = "The path of the resource") @QueryParam("transferred_resource_path") String path,
@ApiParam(value = "Choose format in which to get the response", allowableValues = RodaConstants.API_DELETE_MEDIA_TYPES) @QueryParam(RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT) String acceptFormat)
throws RODAException {
String mediaType = ApiUtils.getMediaType(acceptFormat, request);
// get user
User user = UserUtility.getApiUser(request);
// delegate action to controller
org.roda.core.data.v2.ip.TransferredResource resource = Browser.reindexTransferredResource(user, path);
return Response.ok(resource, mediaType).build();
}
}