aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferEntity.java
diff options
context:
space:
mode:
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.java235
1 files changed, 235 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..7799fe8f
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferEntity.java
@@ -0,0 +1,235 @@
+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.utils.StreamUtil;
+
+import eu.siacs.conversations.entities.DownloadableFile;
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.entities.Transferable;
+import eu.siacs.conversations.persistance.FileBackend;
+
+/**
+ *
+ */
+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;
+ }
+}