Coverage Summary for Class: GalleryMediaContent (org.kitodo.production.forms.dataeditor)
Class |
Class, %
|
Method, %
|
Line, %
|
GalleryMediaContent |
0%
(0/1)
|
0%
(0/18)
|
0%
(0/43)
|
/*
* (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
*
* This file is part of the Kitodo project.
*
* It is licensed under GNU General Public License version 3 or later.
*
* For the full copyright and license information, please read the
* GPL3-License.txt file that was distributed with this source code.
*/
package org.kitodo.production.forms.dataeditor;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.Objects;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.kitodo.api.dataformat.View;
import org.kitodo.production.enums.MediaContentType;
import org.kitodo.production.services.ServiceManager;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
/**
* A single media content in the media gallery.
*/
public class GalleryMediaContent {
private static final Logger logger = LogManager.getLogger(GalleryMediaContent.class);
/**
* Identifier for the media content.
*/
private final String id;
/**
* URI to content for media preview.
*/
private final URI previewUri;
/**
* URI to the content for the media view.
*/
private final URI mediaViewUri;
private final View view;
private final String previewMimeType;
private final String mediaViewMimeType;
/**
* Type of the current object.
*
* <p>Mime types are used for streaming, but they are not the representative type of the object. Therefore, we need
* this fixed type for distinction.</p>
*/
private final MediaContentType type;
/**
* Stores the primefaces tree node id of the corresponding tree node of the logical structure
* tree. This id can be used in the user interface to identify which gallery thumbnail
* corresponds to which tree node in the logical structure tree.
*
* <p>It consists of a sequence of numbers separated by underscore, e.g. "0_1_4". Each number
* describes the position of a child amongst its siblings at that level. For example, "0_1_4"
* references the node that is reached when moving from root node to leaf node using the first
* child, then the second child, and then the fifth child.</p>
*
* <p>The root node itself is never referenced, as it is not visualized anyway.</p>
*/
private String logicalTreeNodeId;
/**
* Creates a new gallery media content.
*
* @param canonical
* the canonical part of the file name, used as the identifier for the media content
* @param previewUri
* URI to content for media preview. Can be {@code null}, then a placeholder is used.
* @param mediaViewUri
* URI to the content for the media view. Can be {@code null}, then no media view is offered.
*/
GalleryMediaContent(MediaContentType type, View view, String canonical, String previewMimeType, URI previewUri,
String mediaViewMimeType, URI mediaViewUri, String logicalTreeNodeId) {
this.type = type;
this.view = view;
this.id = canonical;
this.previewMimeType = previewMimeType;
this.previewUri = previewUri;
this.mediaViewMimeType = mediaViewMimeType;
this.mediaViewUri = mediaViewUri;
this.logicalTreeNodeId = logicalTreeNodeId;
}
/**
* Returns the ID of the media file. The ID is needed to create a unique URI
* to correctly reference the media file within a JSF output loop.
*
* @return the media file ID
*/
public String getId() {
return id;
}
/**
* Returns the shortened ID of the media by removing leading zeros.
* @return the shortened id of the media file
*/
public String getShortId() {
if (Objects.nonNull(id)) {
return id.replaceFirst("^0+(?!$)", "");
} else {
return "-";
}
}
/**
* Get the mime type of the selected media view of the project.
*
* @return the mime type of media view
*/
public String getMediaViewMimeType() {
return mediaViewMimeType;
}
/**
* Get the mime type of the selected preview of the project.
*
* @return the mime type of preview
*/
public String getPreviewMimeType() {
return previewMimeType;
}
/**
* Returns the media content. This is the method that is called when the web browser wants to retrieve the media
* file itself.
*
* @return a Primefaces object that handles the output of media data
*/
public StreamedContent getMediaViewData() {
return sendData(mediaViewUri, mediaViewMimeType);
}
/**
* Returns the order number of the medium (to be displayed to the user).
*
* @return the order number
*/
public String getOrder() {
return Integer.toString(view.getPhysicalDivision().getOrder());
}
/**
* Returns the order label of the medium.
*
* @return the order label
*/
public String getOrderlabel() {
return view.getPhysicalDivision().getOrderlabel();
}
/**
* Returns the media content of the preview media. This is the method that
* is called through the gallery panel using a media ID.
*
* @return a Primefaces object that handles the output of media data
*/
StreamedContent getPreviewData() {
return sendData(previewUri, previewMimeType);
}
/**
* Indicates if there is a media view for this media. Production is able to
* work with media files for which there is currently no adequate display
* capability in web browsers. In this case, the media view is not offered.
* This is configured by selecting a folder for the media view in the
* project or not.
*
* @return if there is a media view for this media
*/
public boolean isShowingInMediaView() {
return Objects.nonNull(mediaViewUri);
}
/**
* Indicates if there is a media preview for this media. Production is able
* to work with media files for which there is currently no adequate display
* capability in web browsers. In this case, a placeholder is displayed.
* This is configured by selecting a folder for the media preview in the
* project or not.
*
* @return if there is a media preview for this media
*/
public boolean isShowingInPreview() {
return Objects.nonNull(previewUri);
}
/**
* Returns the type of gallery media content object.
*
* @return the type of gallery media content object.
*/
public String getType() {
return type.name();
}
/**
* Method for output of URL-referenced media content.
*
* @param uri
* internal URI of the media file to be transferred
* @param mimeType
* the Internet MIME type of the media file
* @return a Primefaces object that handles the output of media data
*/
private StreamedContent sendData(URI uri, String mimeType) {
/*
* During the construction of the HTML page, only an URL for the media
* file is generated.
*/
if (FacesContext.getCurrentInstance().getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return DefaultStreamedContent.builder().build();
}
/*
* Output of media data when the browser retrieves this URL. Note that
* we are NOT ALLOWED TO close the InputStream at this point. Faces does
* that after transferring the data.
*/
try {
InputStream viewData = ServiceManager.getFileService().read(uri);
return DefaultStreamedContent.builder().stream(() -> viewData).contentType(mimeType)
.name(Paths.get(uri.getPath()).getFileName().toString()).contentLength(viewData.available())
.build();
} catch (IOException e) {
logger.catching(e);
String errorpage = "<html>" + System.lineSeparator() + "<h1>Error!</h1>" + System.lineSeparator() + "<p>"
+ e.getClass().getSimpleName() + ": " + e.getMessage() + "</p>" + System.lineSeparator() + "</html>"
+ System.lineSeparator();
ByteArrayInputStream errorPage = new ByteArrayInputStream(errorpage.getBytes(StandardCharsets.UTF_8));
return DefaultStreamedContent.builder().stream(() -> errorPage).contentType("text/html")
.name("errorpage.html").contentEncoding("UTF-8").build();
}
}
public View getView() {
return view;
}
/**
* Check if the GalleryMediaContent's PhysicalDivision is assigned to several LogicalDivisions.
*
* @return {@code true} when the PhysicalDivision is assigned to more than one logical element
*/
public boolean isAssignedSeveralTimes() {
if (Objects.nonNull(view) && Objects.nonNull(view.getPhysicalDivision())) {
return view.getPhysicalDivision().getLogicalDivisions().size() > 1;
}
return false;
}
/**
* Returns the id to the corresponding tree node of the primefaces tree component used to
* visualize the logical structure tree.
*
* @return the logical tree node id
*/
public String getLogicalTreeNodeId() {
return this.logicalTreeNodeId;
}
/**
* Sets the id of the corresponding tree node of the primefaces tree component used to visualize the logical
* structure tree.
*
* @param treeNodeId
* the tree node id
*/
public void setLogicalTreeNodeId(String treeNodeId) {
this.logicalTreeNodeId = treeNodeId;
}
}