package de.tum.in.www1.jReto.connectivity; import java.util.UUID; /** * A Transfer object represents a data transfer between two or more peers. * It has two subclasses, InTransfer and OutTransfer, which represent an incoming transfer (i.e. a data transfer that is being received) and an outgoing transfer (i.e. a data transfer that is being sent to some other peer). * OutTransfers are created by calling one of the send methods on the Connection class. * InTransfers are created by the Connection class when the connected peer starts a data transfer. At this point, the connection's onTransfer event is invoked. Thus, InTransfers can be obtained by using the onTransfer event exposed by the Connection class. * * This class exposes the following events for which handlers can be set using the appropriate methods: * * - onStart: Called when the transfer starts. If this property is set when the transfer is already started, the closure is called immediately. * - onProgress: Called whenever the transfer makes progress. * - onComplete: Called when the transfer completes successfully. To receive the data from an incoming transfer, use onCompleteData or onPartialData of InTransfer. * - onCancel: Called when the transfer is cancelled. * - onEnd: Called when the transfer ends, either by cancellation or completion. * * All of these events are optional. Note: Incoming transfers have separate events that give access to the received data. See the InTransfer class documentation. */ public abstract class Transfer { public static interface StartHandler { void onStart(Transfer transfer); } public static interface ProgressHandler { void onProgress(Transfer transfer); } public static interface CompletionHandler { void onComplete(Transfer transfer); } public static interface CancellationHandler { void onCancel(Transfer transfer); } public static interface EndHandler { void onEnd(Transfer transfer); } // Called when the transfer starts. If this property is set when the transfer is already started, the closure is called immediately. private StartHandler startHandler; // Called whenever the transfer makes progress. private ProgressHandler progressHandler; // Called when the transfer completes successfully. To receive the data from an incoming transfer, use onCompleteData or onPartialData of InTransfer. private CompletionHandler completionHandler; // Called when the transfer is cancelled. private CancellationHandler cancellationHandler; // Called when the transfer ends, either by cancellation or completion. private EndHandler endHandler; public StartHandler getOnStart() { return startHandler; } /** Sets the onStart event handler. */ public void setOnStart(StartHandler startHandler) { this.startHandler = startHandler; if (this.isStarted) startHandler.onStart(this); } public ProgressHandler getOnProgress() { return progressHandler; } /** Sets the onProgress event handler. */ public void setOnProgress(ProgressHandler progressHandler) { this.progressHandler = progressHandler; } public CompletionHandler getOnComplete() { return completionHandler; } /** Sets the onComplete event handler. */ public void setOnComplete(CompletionHandler completionHandler) { this.completionHandler = completionHandler; } public CancellationHandler getOnCancel() { return cancellationHandler; } /** Sets the onCancel event handler. */ public void setOnCancel(CancellationHandler cancellationHandler) { this.cancellationHandler = cancellationHandler; } public EndHandler getOnEnd() { return endHandler; } /** Sets the onEnd event handler. */ public void setOnEnd(EndHandler endHandler) { this.endHandler = endHandler; } /** Whether the transfer was been started */ private boolean isStarted; /** Whether the transfer was completed successfully */ private boolean isCompleted; /** Whether the transfer was cancelled */ private boolean isCancelled; /** The transfer's length in bytes*/ private final int length; /** The transfer's current progress in bytes */ private int progress; /** Indicates if the transfer is currently interrupted. This occurs, for example, when a connection closes unexpectedly. The transfer is resumed automatically on reconnect. */ private boolean isInterrupted; /** The transfer's identifier */ private final UUID identifier; /** The transfer's manager. */ private final TransferManager transferManager; /** * Constructs a Transfer. * @param manager The TransferManager responsible for this transfer. * @param length The total length of the transfer in bytes. * @param identifier The transfer's identifier. */ public Transfer(TransferManager transferManager, int length, UUID identifier) { this.length = length; this.identifier = identifier; this.transferManager = transferManager; } /** Whether all data was sent. */ public boolean getIsAllDataTransmitted() { return this.progress == this.length; } /** The transfer's current progress in bytes */ public int getProgress() { return this.progress; } /** The transfer's identifier */ public UUID getIdentifier() { return this.identifier; } /** The transfer's length in bytes*/ public int getLength() { return this.length; } /** Cancels the transfer. */ public abstract void cancel(); /** Updates the transfer's progress. */ void updateProgress(int numberOfBytes) { if (this.length < this.progress+numberOfBytes) throw new IllegalArgumentException("You may not update the progress beyond the Transfer's length."); this.progress += numberOfBytes; this.confirmProgress(); if (this.getIsAllDataTransmitted()) this.confirmCompletion(); } void setInterrupted(boolean interrupted) { this.isInterrupted = interrupted; } public boolean getIsInterrupted() { return this.isInterrupted; } /** Whether the transfer was been started */ public boolean getIsStarted() { return this.isStarted; } /** Whether the transfer was completed successfully */ public boolean getIsCompleted() { return this.isCompleted; } /** Whether the transfer was cancelled */ public boolean getIsCancelled() { return this.isCancelled; } /** Call to change the transfer's state to started and dispatch the associated events. */ void confirmStart() { this.isStarted = true; if (this.startHandler != null) this.startHandler.onStart(this); } /** Call to confirm updated progress and dispatch the associated events. */ void confirmProgress() { if (this.progressHandler != null) this.progressHandler.onProgress(this); } /** Call to change thet transfer's state to cancelled and dispatch the associated events. */ void confirmCancel() { this.isCancelled = true; if (this.cancellationHandler != null) this.cancellationHandler.onCancel(this); this.confirmEnd(); } /** Call to change thet transfer's state to completed and dispatch the associated events. */ void confirmCompletion() { this.isCompleted = true; if (this.completionHandler != null) this.completionHandler.onComplete(this); this.confirmEnd(); } /** Call to change thet transfer's state to ended, dispatch the associated events, and clean up events. */ void confirmEnd() { if (this.endHandler != null) this.endHandler.onEnd(this); } /** Sets the transfer's progress. */ void setProgress(int progress) { this.progress = progress; } TransferManager getTransferManager() { return this.transferManager; } }