| /******************************************************************************* |
| * Copyright (c) 2020 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| *******************************************************************************/ |
| package org.eclipse.mdm.businessobjects.boundary; |
| |
| import static org.eclipse.mdm.businessobjects.boundary.ResourceConstants.REQUESTPARAM_ID; |
| import static org.eclipse.mdm.businessobjects.boundary.ResourceConstants.REQUESTPARAM_REMOTEPATH; |
| import static org.eclipse.mdm.businessobjects.boundary.ResourceConstants.REQUESTPARAM_SOURCENAME; |
| import static org.eclipse.mdm.businessobjects.service.EntityService.V; |
| |
| import java.io.InputStream; |
| |
| import javax.ejb.EJB; |
| import javax.ws.rs.Consumes; |
| import javax.ws.rs.DELETE; |
| import javax.ws.rs.GET; |
| import javax.ws.rs.POST; |
| import javax.ws.rs.Path; |
| import javax.ws.rs.PathParam; |
| import javax.ws.rs.Produces; |
| import javax.ws.rs.core.MediaType; |
| import javax.ws.rs.core.Response; |
| import javax.ws.rs.core.Response.Status; |
| |
| import org.eclipse.mdm.api.base.model.Environment; |
| import org.eclipse.mdm.api.base.model.FileLink; |
| import org.eclipse.mdm.api.base.model.FilesAttachable; |
| import org.eclipse.mdm.api.base.model.MimeType; |
| import org.eclipse.mdm.businessobjects.control.FileLinkActivity; |
| import org.eclipse.mdm.businessobjects.entity.FileSize; |
| import org.eclipse.mdm.businessobjects.entity.MDMEntityResponse; |
| import org.eclipse.mdm.businessobjects.entity.MDMFileLink; |
| import org.eclipse.mdm.businessobjects.service.EntityService; |
| import org.eclipse.mdm.businessobjects.utils.Serializer; |
| import org.eclipse.mdm.businessobjects.utils.ServiceUtils; |
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; |
| import org.glassfish.jersey.media.multipart.FormDataParam; |
| |
| import io.swagger.v3.oas.annotations.Operation; |
| import io.swagger.v3.oas.annotations.Parameter; |
| import io.swagger.v3.oas.annotations.media.ArraySchema; |
| import io.swagger.v3.oas.annotations.media.Content; |
| import io.swagger.v3.oas.annotations.media.Schema; |
| import io.swagger.v3.oas.annotations.responses.ApiResponse; |
| import io.vavr.Tuple; |
| |
| /** |
| * Subresource for {@link FilesAttachable}s. |
| * |
| * @author Johannes Stamm, peak-Solution GmbH |
| * |
| */ |
| public class FilesAttachableSubresource { |
| |
| @EJB |
| private EntityService entityService; |
| |
| @EJB |
| private FileLinkActivity fileLinkActivity; |
| |
| private Class<? extends FilesAttachable> fileAttachableClass; |
| |
| /** |
| * Set the Entity class of the parent resource. This method has to be called |
| * right after the resource was initialized by the container. The entity class |
| * is used to distinguish the type of the parent resource. |
| * |
| * This method is package-private to workaround an issue in WELD complaining |
| * about: Parameter 1 of type ... is not resolvable to a concrete type. |
| * |
| * @param fileAttachableClass the Entity class of the parent resource |
| */ |
| void setEntityClass(Class<? extends FilesAttachable> fileAttachableClass) { |
| this.fileAttachableClass = fileAttachableClass; |
| } |
| |
| /** |
| * Stream the contents of a file link. |
| * |
| * @param sourceName name of the source (MDM {@link Environment} name) |
| * @param id The identifier of the {@link FilesAttachable} which |
| * contains the {@link FileLink} |
| * @param remotePath The remote path of the {@link FileLink} to identify, which |
| * {@link FileLink}'s content is requests. |
| * @return The content of the file as {@link javax.ws.rs.core.StreamingOutput}. |
| * The response also has the MimeType set according to |
| * {@link FileLink#getMimeType()}. |
| */ |
| @GET |
| @Operation(summary = "Stream the contents of a file link", responses = { |
| @ApiResponse(description = "The content of the file link as a stream. MimeType is set to that of the file link.", content = @Content(schema = @Schema(implementation = MDMEntityResponse.class))), |
| @ApiResponse(responseCode = "400", description = "Invalid ID or remote path supplied") }) |
| @Path("/{" + REQUESTPARAM_REMOTEPATH + "}") |
| public Response streamFileLink( |
| @Parameter(description = "Name of the MDM datasource", required = true) @PathParam(REQUESTPARAM_SOURCENAME) String sourceName, |
| @Parameter(description = "ID of the Test containing the file link", required = true) @PathParam(REQUESTPARAM_ID) String id, |
| @Parameter(description = "The remote path of the file link whose content is to be retrieved", required = true) @PathParam(REQUESTPARAM_REMOTEPATH) String remotePath) { |
| |
| return entityService.find(V(sourceName), fileAttachableClass, V(id)) |
| .map(filesAttachable -> Tuple.of(filesAttachable, |
| fileLinkActivity.findFileLinkAtFileAttachable(remotePath, filesAttachable))) |
| .map(tuple -> Tuple.of(fileLinkActivity.toStreamingOutput(sourceName, tuple._1, tuple._2), |
| fileLinkActivity.toMediaType(tuple._2))) |
| .map(tuple -> Response.ok(tuple._1, tuple._2).build()).get(); |
| } |
| |
| /** |
| * Deletes attached file from {@link FilesAttachable}. |
| * |
| * @param sourceName name of the source (MDM {@link Environment} name) |
| * @param id The identifier of the {@link FilesAttachable} which |
| * contains the {@link FileLink} |
| * @param remotePath The remote path of the {@link FileLink} to delete. |
| * @return |
| */ |
| @DELETE |
| @Operation(summary = "Deletes an attached file.", responses = { |
| @ApiResponse(description = "The deleted file link", content = @Content(schema = @Schema(implementation = MDMFileLink.class))), |
| @ApiResponse(responseCode = "400", description = "Error") }) |
| @Produces(MediaType.APPLICATION_JSON) |
| @Path("/{" + REQUESTPARAM_REMOTEPATH + "}") |
| public Response deleteFile( |
| @Parameter(description = "Name of the MDM datasource", required = true) @PathParam(REQUESTPARAM_SOURCENAME) String sourceName, |
| @Parameter(description = "ID of the FilesAttachable containing the file link", required = true) @PathParam(REQUESTPARAM_ID) String id, |
| @Parameter(description = "The remote path of the file link whose content is to be retrieved", required = true) @PathParam(REQUESTPARAM_REMOTEPATH) String remotePath) { |
| |
| return entityService.find(V(sourceName), fileAttachableClass, V(id)) |
| .map(fileAttachable -> fileLinkActivity.deleteFileLink(sourceName, fileAttachable, remotePath)) |
| .map(fileLink -> ServiceUtils.toResponse(Serializer.serializeFileLink(fileLink), Status.OK)).get(); |
| } |
| |
| /** |
| * Creates new {@link FileLink} for {@link FilesAttachable}. |
| * |
| * @param sourceName name of the source (MDM {@link Environment} name) |
| * @param body The {@link FileLink} to create. |
| * @return |
| */ |
| @POST |
| @Operation(summary = "Attaches a new file.", responses = { |
| @ApiResponse(description = "The stored file link.", content = @Content(schema = @Schema(implementation = MDMFileLink.class))), |
| @ApiResponse(responseCode = "400", description = "Error") }) |
| @Produces(MediaType.APPLICATION_JSON) |
| @Consumes(MediaType.MULTIPART_FORM_DATA) |
| public Response createFile( |
| @Parameter(description = "Name of the MDM datasource", required = true) @PathParam(REQUESTPARAM_SOURCENAME) String sourceName, |
| @Parameter(description = "ID of the FilesAttachable containing the file link", required = true) @PathParam(REQUESTPARAM_ID) String id, |
| @Parameter(description = "InputStream containing file data", required = true) @FormDataParam("file") InputStream fileInputStream, |
| @Parameter(description = "Meta data describing file", required = true) @FormDataParam("file") FormDataContentDisposition cdh, |
| @Parameter(description = "File description", required = true) @FormDataParam("description") String description, |
| @Parameter(description = "Mimetype of the file", required = true) @FormDataParam("mimeType") MimeType mimeType) { |
| |
| return entityService.find(V(sourceName), fileAttachableClass, V(id)) |
| .map(fileAttachable -> fileLinkActivity.createFile(sourceName, fileAttachable, |
| ServiceUtils.convertIso8859toUtf8(cdh.getFileName()), fileInputStream, description, mimeType)) |
| .map(fileLink -> ServiceUtils.toResponse(Serializer.serializeFileLink(fileLink), Status.OK)).get(); |
| } |
| |
| /** |
| * Load the file size of a file link. |
| * |
| * @param sourceName name of the source (MDM {@link Environment} name) |
| * @param id The identifier of the {@link FilesAttachable} which |
| * contains the {@link FileLink} |
| * @param remotePath The remote path of the {@link FileLink} to identify, which |
| * {@link FileLink}'s content is requests. |
| * @return The serialized {@link FileLink} with the size. |
| */ |
| @GET |
| @Operation(summary = "Returns the file size of file link.", responses = { |
| @ApiResponse(description = "The file size of the requested file link.", content = @Content(schema = @Schema(implementation = FileSize.class))), |
| @ApiResponse(responseCode = "400", description = "Error") }) |
| @Produces(MediaType.APPLICATION_JSON) |
| @Path("/size/{" + REQUESTPARAM_REMOTEPATH + "}") |
| public Response loadFileSize( |
| @Parameter(description = "Name of the MDM datasource", required = true) @PathParam(REQUESTPARAM_SOURCENAME) String sourceName, |
| @Parameter(description = "The identifier of the FilesAttachable containing the file links", required = true) @PathParam(REQUESTPARAM_ID) String id, |
| @Parameter(description = "The remote path of the file link whose size is to be retrieved", required = true) @PathParam(REQUESTPARAM_REMOTEPATH) String remotePath) { |
| |
| return entityService.find(V(sourceName), fileAttachableClass, V(id)) |
| .map(filesAttachable -> Tuple.of(filesAttachable, |
| fileLinkActivity.findFileLinkAtFileAttachable(remotePath, filesAttachable))) |
| .map(tuple -> fileLinkActivity.loadFileSize(sourceName, tuple._1, tuple._2)) |
| .map(fileSize -> ServiceUtils.toResponse(fileSize, Status.OK)).get(); |
| } |
| |
| /** |
| * Load the file sizes for all {@link FileLink}s of the {@link FilesAttachable}. |
| * |
| * @param sourceName name of the source (MDM {@link Environment} name) |
| * @param id The identifier of the {@link FilesAttachable} which |
| * contains the {@link FileLink} |
| * @param remotePath The remote path of the {@link FileLink} to identify, which |
| * {@link FileLink}'s content is requests. |
| * @return The serialized {@link FileLink} with the size. |
| */ |
| @GET |
| @Operation(summary = "Returns the sizes of all file links attached to a FilesAttachable.", responses = { |
| @ApiResponse(description = "The file size of the requested file link.", content = @Content(array = @ArraySchema(schema = @Schema(implementation = FileSize.class)))), |
| @ApiResponse(responseCode = "400", description = "Error") }) |
| @Produces(MediaType.APPLICATION_JSON) |
| @Path("/sizes") |
| public Response loadFileSizes( |
| @Parameter(description = "Name of the MDM datasource", required = true) @PathParam(REQUESTPARAM_SOURCENAME) String sourceName, |
| @Parameter(description = "ID of the FilesAttachable containing the file link", required = true) @PathParam(REQUESTPARAM_ID) String id) { |
| |
| return entityService.find(V(sourceName), fileAttachableClass, V(id)) |
| .map(filesAttachable -> fileLinkActivity.loadFileSizes(sourceName, filesAttachable)) |
| .map(fileSizes -> ServiceUtils.toResponse(fileSizes, Status.OK)).get(); |
| } |
| } |