diff options
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferEntity.java')
-rw-r--r-- | src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferEntity.java | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferEntity.java b/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferEntity.java new file mode 100644 index 00000000..e1b40fa6 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferEntity.java @@ -0,0 +1,234 @@ +package de.thedevstack.conversationsplus.services.filetransfer; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import de.thedevstack.conversationsplus.entities.DownloadableFile; +import de.thedevstack.conversationsplus.entities.Message; +import de.thedevstack.conversationsplus.entities.Transferable; +import de.thedevstack.conversationsplus.persistance.FileBackend; +import de.thedevstack.conversationsplus.utils.StreamUtil; + +/** + * + */ +public class FileTransferEntity implements Transferable { + /** + * Listeners to inform about a status change. + */ + private final List<FileTransferStatusListener> statusListeners = new ArrayList<>(); + /** + * The associated message. + */ + private final Message message; + /** + * Number of attempts. + */ + private int attempts = 0; + /** + * The status of the file transfer. + */ + private FileTransferStatusEnum transferStatus; + /** + * Number of bytes transmitted. + */ + private long transmitted = 0; + /** + * The associated file. + */ + private DownloadableFile file; + /** + * The associated file as stream. + */ + private InputStream fileInputStream; + + /** + * Initializes the FileTransferEntity based on the associated message. + * This initialization includes loading the file and associating this transferable to the message. + * @param message the message in which the file to transfer is contained. + */ + public FileTransferEntity(Message message) { + this.message = message; + this.message.setTransferable(this); + this.file = FileBackend.getFile(message, false); + } + + /** + * Start something. + * Empty implementation since documentation in interface is missing. + * @return <code>false</code> + */ + @Override + public boolean start() { + return false; + } + + /** + * Returns the global transferable status. + * + * @return {@value STATUS_FAILED} if #isFailed returns <code>true</code>, {@value STATUS_UPLOADING} otherwise + */ + @Override + public int getStatus() { + int status = (isFailed()) ? STATUS_FAILED : STATUS_UPLOADING; + return status; + } + + /** + * Returns the expected file size of the underlying file. + * @return the expected file size or 0 if no file is associated. + */ + @Override + public long getFileSize() { + return file == null ? 0 : file.getExpectedSize(); + } + + /** + * Calculates the current progress in percent. + * + * @return the current progress in percent + */ + @Override + public int getProgress() { + if (file == null) { + return 0; + } + return (int) ((((double) transmitted) / file.getExpectedSize()) * 100); + } + + /** + * Cancels the file transfer and informs the listeners about cancellation. + */ + @Override + public void cancel() { + this.transferStatus = FileTransferStatusEnum.CANCELED; + + this.close(); + + for (FileTransferStatusListener listener : this.statusListeners) { + listener.onCancel(this); + } + } + + /** + * Starts an transfer attempt. + */ + public void startAttempt() { + this.attempts++; + this.transferStatus = FileTransferStatusEnum.TRANSFERRING; + } + + /** + * Fails an file transfer and informs the listeners about failure. + * + * @param failureReason the reason of failure. + */ + public void fail(FileTransferFailureReason failureReason) { + this.transferStatus = FileTransferStatusEnum.FAILED; + + this.close(); + + failureReason.setAttempt(this.attempts); + for (FileTransferStatusListener listener : this.statusListeners) { + listener.onFailure(this, failureReason); + } + } + + /** + * Updates the progress by adding parameter value to current progress value. + * + * @param progress the number of newly transferred bytes + */ + public void updateProgress(long progress) { + if (0 == this.attempts) { + this.startAttempt(); + } + this.transmitted += progress; + } + + /** + * Set the status of the file transfer to FileTransferStatusEnum#TRANSFERRED and informs the listeners about success. + */ + public void transferred() { + this.transferStatus = FileTransferStatusEnum.TRANSFERRED; + + this.close(); + + for (FileTransferStatusListener listener : this.statusListeners) { + listener.onSuccess(this); + } + } + + /** + * Closes the file input stream (if it is not yet closed) and removes association with message. + */ + private void close() { + StreamUtil.close(this.fileInputStream); + this.getMessage().setTransferable(null); + } + + /** + * Whether the file is transferred or not. + * @return <code>true</code> if the file is successfully transferred, <code>false</code> otherwise + */ + public boolean isTransferred() { + return FileTransferStatusEnum.TRANSFERRED == this.transferStatus; + } + + /** + * Whether the file transfer is canceled or not. + * @return <code>true</code> if the file transfer was canceled, <code>false</code> otherwise + */ + public boolean isCanceled() { + return FileTransferStatusEnum.CANCELED == this.transferStatus; + } + + /** + * Whether the file transfer failed or not. + * @return <code>true</code> if the file transfer failed, <code>false</code> otherwise + */ + public boolean isFailed() { + return FileTransferStatusEnum.FAILED == this.transferStatus; + } + + public void setFileInputStream(InputStream fileInputStream) { + this.fileInputStream = fileInputStream; + } + + public InputStream getFileInputStream() { + return fileInputStream; + } + + public Message getMessage() { + return message; + } + + public DownloadableFile getFile() { + return file; + } + + public void addFileTransferStatusListener(FileTransferStatusListener... listeners) { + this.statusListeners.addAll(Arrays.asList(listeners)); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FileTransferEntity that = (FileTransferEntity) o; + + String uuid = message != null ? message.getUuid() : null; + String thatUuid = that.message != null ? that.message.getUuid() : null; + + return uuid != null ? uuid.equals(thatUuid) : thatUuid == null; + + } + + @Override + public int hashCode() { + return message != null && message.getUuid() != null ? message.getUuid().hashCode() : 0; + } +} |