| /******************************************************************************* |
| * 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_ATTRIBUTENAME; |
| import static org.eclipse.mdm.businessobjects.boundary.ResourceConstants.REQUESTPARAM_CONTEXTCOMPONENTNAME; |
| import static org.eclipse.mdm.businessobjects.boundary.ResourceConstants.REQUESTPARAM_CONTEXTTYPE; |
| 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.ContextDescribable; |
| import org.eclipse.mdm.api.base.model.ContextType; |
| import org.eclipse.mdm.api.base.model.Environment; |
| import org.eclipse.mdm.api.base.model.FileLink; |
| import org.eclipse.mdm.api.base.model.MimeType; |
| import org.eclipse.mdm.api.base.model.TestStep; |
| 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.Content; |
| import io.swagger.v3.oas.annotations.media.Schema; |
| import io.swagger.v3.oas.annotations.responses.ApiResponse; |
| import io.vavr.Tuple; |
| |
| /** |
| * context files subresource |
| * |
| * @author Johannes Stamm, peak-Solution GmbH |
| * |
| */ |
| public class ContextFilesSubresource { |
| |
| @EJB |
| private FileLinkActivity fileLinkActivity; |
| |
| @EJB |
| private EntityService entityService; |
| |
| private Class<? extends ContextDescribable> contextDescribableClass; |
| |
| /** |
| * 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 contextDescribableClass the Entity class of the parent resource |
| */ |
| void setEntityClass(Class<? extends ContextDescribable> contextDescribableClass) { |
| this.contextDescribableClass = contextDescribableClass; |
| } |
| |
| /** |
| * Creates new {@link FileLink} for {@link TestStep}. |
| * |
| * @param sourceName name of the source (MDM {@link Environment} name) |
| * @param body The {@link FileLink} to create. |
| * @return |
| */ |
| @POST |
| @Operation(summary = "Creates a new file on a context attribute.", 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 parent ContextDescribable", required = true) @PathParam(REQUESTPARAM_ID) String contextDescribableId, |
| @Parameter(description = "ContextType of the Component holding the attribute with the FileLink", required = true) @PathParam(REQUESTPARAM_CONTEXTTYPE) ContextType contextType, |
| @Parameter(description = "Name of the ContextComponent holding the attribute with the FileLink", required = true) @PathParam(REQUESTPARAM_CONTEXTCOMPONENTNAME) String contextComponentName, |
| @Parameter(description = "Name of the Attribute holding the FileLink", required = true) @PathParam(REQUESTPARAM_ATTRIBUTENAME) String attributeName, |
| @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), contextDescribableClass, V(contextDescribableId)) |
| .map(contextDescribable -> fileLinkActivity.createFile(sourceName, contextDescribable, |
| ServiceUtils.convertIso8859toUtf8(cdh.getFileName()), fileInputStream, description, mimeType, |
| contextType, contextComponentName, attributeName)) |
| .map(fileLink -> ServiceUtils.toResponse(Serializer.serializeFileLink(fileLink), Status.OK)).get(); |
| } |
| |
| @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 parent ContextDescribable", required = true) @PathParam(REQUESTPARAM_ID) String contextDescribableId, |
| @Parameter(description = "ContextType of the Component holding the attribute with the FileLink", required = true) @PathParam(REQUESTPARAM_CONTEXTTYPE) ContextType contextType, |
| @Parameter(description = "Name of the ContextComponent holding the attribute with the FileLink", required = true) @PathParam(REQUESTPARAM_CONTEXTCOMPONENTNAME) String contextComponentName, |
| @Parameter(description = "Name of the Attribute holding the FileLink", required = true) @PathParam(REQUESTPARAM_ATTRIBUTENAME) String attributeName, |
| @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), contextDescribableClass, V(contextDescribableId)) |
| .map(contextDescribable -> Tuple.of(contextDescribable, |
| fileLinkActivity.findFileLinkInContext(remotePath, sourceName, contextDescribable, contextType, |
| contextComponentName, attributeName))) |
| .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(); |
| } |
| |
| @GET |
| @Operation(summary = "Returns the size of a file in bytes.", responses = { |
| @ApiResponse(description = "The file size of the requested remote path.", 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 = "ID of the parent ContextDescribable", required = true) @PathParam(REQUESTPARAM_ID) String contextDescribableId, |
| @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), contextDescribableClass, V(contextDescribableId)) |
| .map(contextDescribabale -> fileLinkActivity.loadFileSize(sourceName, contextDescribabale, |
| FileLink.newRemote(remotePath, null, null))) |
| .map(fileSize -> Response.ok(fileSize).build()).get(); |
| } |
| |
| /** |
| * Deletes attached file from {@link ContextDescirbable}. |
| * |
| * @param sourceName name of the source (MDM {@link Environment} name) |
| * @param id The identifier of the {@link ContextDescirbable} which |
| * contains the {@link FileLink} |
| * @param remotePath The remote path of the {@link FileLink} to delete. |
| * @return |
| */ |
| @DELETE |
| @Operation(summary = "Deletes an attached file from a context attribute.", 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 parent ContextDescribable", required = true) @PathParam(REQUESTPARAM_ID) String contextDescribableId, |
| @Parameter(description = "ContextType of the Component holding the attribute with the FileLink", required = true) @PathParam(REQUESTPARAM_CONTEXTTYPE) ContextType contextType, |
| @Parameter(description = "Name of the ContextComponent holding the attribute with the FileLink", required = true) @PathParam(REQUESTPARAM_CONTEXTCOMPONENTNAME) String contextComponentName, |
| @Parameter(description = "Name of the Attribute holding the FileLink", required = true) @PathParam(REQUESTPARAM_ATTRIBUTENAME) String attributeName, |
| @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), contextDescribableClass, V(contextDescribableId)) |
| .map(contextDescribable -> fileLinkActivity.deleteFileLink(sourceName, contextDescribable, contextType, |
| contextComponentName, attributeName, remotePath)) |
| .map(fileLink -> ServiceUtils.toResponse(Serializer.serializeFileLink(fileLink), Status.OK)).get(); |
| } |
| } |