Add handler for when a channel can not be joined.
[xudocci.git] / src / main / java / net / pterodactylus / xdcc / data / Download.java
1 /*
2  * XdccDownloader - Download.java - Copyright © 2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.xdcc.data;
19
20 import static com.google.common.base.Preconditions.checkNotNull;
21
22 import java.io.OutputStream;
23 import java.net.InetAddress;
24 import java.util.Comparator;
25 import java.util.concurrent.atomic.AtomicLong;
26 import java.util.concurrent.atomic.AtomicReference;
27
28 import net.pterodactylus.irc.DccReceiver;
29
30 import com.google.common.base.Function;
31 import com.google.common.base.Optional;
32 import com.google.common.base.Predicate;
33
34 /**
35  * Information about an ongoing download.
36  *
37  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
38  */
39 public class Download {
40
41         /** Predicate that identifies downloads that have started. */
42         public static final Predicate<Download> FILTER_RUNNING = new Predicate<Download>() {
43
44                 @Override
45                 public boolean apply(Download download) {
46                         return download.dccReceiver() != null;
47                 }
48         };
49
50         /** {@link Comparator} that sorts downloads by their name. */
51         public static final Comparator<Download> BY_NAME = new Comparator<Download>() {
52
53                 @Override
54                 public int compare(Download leftDownload, Download rightDownload) {
55                         return leftDownload.pack().name().compareToIgnoreCase(rightDownload.pack().name());
56                 }
57         };
58
59         /**  {@link Comparator} that sorts running downloads first. */
60         public static final Comparator<Download> BY_RUNNING = new Comparator<Download>() {
61
62                 @Override
63                 public int compare(Download leftDownload, Download rightDownload) {
64                         return (leftDownload.dccReceiver() != null) ? -1 : (rightDownload.dccReceiver() != null) ? 1 : 0;
65                 }
66         };
67
68         /**
69          * Converts a download into the number of seconds left in the transfer at the
70          * current rate.
71          */
72         public static final Function<Download, Optional<Long>> SECONDS_LEFT = new Function<Download, Optional<Long>>() {
73                 @Override
74                 public Optional<Long> apply(Download download) {
75                         DccReceiver dccReceiver = download.dccReceiver();
76                         if ((dccReceiver == null) || (dccReceiver.size() == -1) || (dccReceiver.currentRate() == 0)) {
77                                 return Optional.absent();
78                         }
79                         long secondsLeft = (dccReceiver.size() - dccReceiver.progress()) / dccReceiver.currentRate();
80                         return Optional.of(secondsLeft);
81                 }
82         };
83
84         /** The bot that is being downloaded from. */
85         private final Bot bot;
86
87         /** The pack that is being downloaded. */
88         private final Pack pack;
89
90         /** The name of the file being downloaded. */
91         private final AtomicReference<String> filename = new AtomicReference<String>();
92
93         /** The size of the file being downloaded. */
94         private final AtomicLong filesize = new AtomicLong();
95
96         /** The remote address. */
97         private final AtomicReference<InetAddress> remoteAddress = new AtomicReference<InetAddress>();
98
99         /** The output stream. */
100         private final AtomicReference<OutputStream> outputStream = new AtomicReference<OutputStream>();
101
102         /** The DCC receiver. */
103         private final AtomicReference<DccReceiver> dccReceiver = new AtomicReference<DccReceiver>();
104
105         /**
106          * Creates a new download.
107          *
108          * @param bot
109          *              The bot offering the download
110          * @param pack
111          *              The pack being downloaded
112          */
113         public Download(Bot bot, Pack pack) {
114                 this.bot = checkNotNull(bot, "bot must not be null");
115                 this.pack = checkNotNull(pack, "pack must not be null");
116         }
117
118         //
119         // ACCESSORS
120         //
121
122         /**
123          * Returns the bot offering the download.
124          *
125          * @return The bot offering the download
126          */
127         public Bot bot() {
128                 return bot;
129         }
130
131         /**
132          * The pack that is being downloaded.
133          *
134          * @return The pack being downloaded
135          */
136         public Pack pack() {
137                 return pack;
138         }
139
140         /**
141          * The full name of the file being written.
142          *
143          * @return The full name of the file
144          */
145         public String filename() {
146                 return filename.get();
147         }
148
149         /**
150          * Returns the size of the file.
151          *
152          * @return The size of the file
153          */
154         public long filesize() {
155                 return filesize.get();
156         }
157
158         /**
159          * Returns the remote address to download from.
160          *
161          * @return The remote address to download from
162          */
163         public InetAddress remoteAddress() {
164                 return remoteAddress.get();
165         }
166
167         /**
168          * The output stream that writes to the file.
169          *
170          * @return The output stream
171          */
172         public OutputStream outputStream() {
173                 return outputStream.get();
174         }
175
176         /**
177          * The DCC receiver that is downloading the file
178          *
179          * @return The DCC receiver
180          */
181         public DccReceiver dccReceiver() {
182                 return dccReceiver.get();
183         }
184
185         //
186         // MUTATORS
187         //
188
189         /**
190          * Sets the full name of the file being downloaded.
191          *
192          * @param filename
193          *              The full name of the file
194          * @return This download
195          */
196         public Download filename(String filename) {
197                 this.filename.set(filename);
198                 return this;
199         }
200
201         /**
202          * Sets the size of the download.
203          *
204          * @param filesize
205          *              The size of the download
206          * @return This download
207          */
208         public Download filesize(long filesize) {
209                 this.filesize.set(filesize);
210                 return this;
211         }
212
213         /**
214          * Sets the remote address of the download.
215          *
216          * @param remoteAddress
217          *              The remote address of the download
218          * @return This download
219          */
220         public Download remoteAddress(InetAddress remoteAddress) {
221                 this.remoteAddress.set(remoteAddress);
222                 return this;
223         }
224
225         /**
226          * Sets the output stream the download is being written to
227          *
228          * @param outputStream
229          *              The output stream
230          * @return This download
231          */
232         public Download outputStream(OutputStream outputStream) {
233                 this.outputStream.set(outputStream);
234                 return this;
235         }
236
237         /**
238          * Sets the DCC receiver that downloads the file.
239          *
240          * @param dccReceiver
241          *              The DCC receiver
242          * @return This download
243          */
244         public Download dccReceiver(DccReceiver dccReceiver) {
245                 this.dccReceiver.set(dccReceiver);
246                 return this;
247         }
248
249         //
250         // OBJECT METHODS
251         //
252
253         @Override
254         public boolean equals(Object object) {
255                 if (!(object instanceof Download)) {
256                         return false;
257                 }
258                 Download download = (Download) object;
259                 return bot().equals(download.bot()) && pack().equals(download.pack());
260         }
261
262         @Override
263         public int hashCode() {
264                 return bot().hashCode() ^ pack().hashCode();
265         }
266
267 }