9e9659d585e0ffd5ad13aac52d6877ea958cc81f
[rhynodge.git] / src / main / java / net / pterodactylus / reactor / states / TorrentState.java
1 /*
2  * Reactor - TorrentState.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.reactor.states;
19
20 import java.nio.charset.Charset;
21 import java.util.Iterator;
22 import java.util.List;
23
24 import net.pterodactylus.reactor.State;
25 import net.pterodactylus.reactor.states.TorrentState.TorrentFile;
26
27 import org.apache.http.NameValuePair;
28 import org.apache.http.client.utils.URLEncodedUtils;
29
30 import com.google.common.collect.Lists;
31
32 /**
33  * {@link State} that contains information about an arbitrary number of torrent
34  * files.
35  *
36  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
37  */
38 public class TorrentState extends AbstractState implements Iterable<TorrentFile> {
39
40         /** The torrent files. */
41         private final List<TorrentFile> files = Lists.newArrayList();
42
43         //
44         // ACCESSORS
45         //
46
47         /**
48          * Adds a torrent file to this state.
49          *
50          * @param torrentFile
51          *            The torrent file to add
52          * @return This state
53          */
54         public TorrentState addTorrentFile(TorrentFile torrentFile) {
55                 files.add(torrentFile);
56                 return this;
57         }
58
59         //
60         // ITERABLE METHODS
61         //
62
63         /**
64          * {@inheritDoc}
65          */
66         @Override
67         public Iterator<TorrentFile> iterator() {
68                 return files.iterator();
69         }
70
71         //
72         // OBJECT METHODS
73         //
74
75         /**
76          * {@inheritDoc}
77          */
78         @Override
79         public String toString() {
80                 return String.format("%s[files=%s]", getClass().getSimpleName(), files);
81         }
82
83         /**
84          * Container for torrent file data.
85          *
86          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
87          */
88         public static class TorrentFile {
89
90                 /** The name of the file. */
91                 private final String name;
92
93                 /** The size of the file. */
94                 private final String size;
95
96                 /** The magnet URI of the file. */
97                 private final String magnetUri;
98
99                 /** The download URI of the file. */
100                 private final String downloadUri;
101
102                 /** The number of files in this torrent. */
103                 private final int fileCount;
104
105                 /** The number of seeds connected to this torrent. */
106                 private final int seedCount;
107
108                 /** The number of leechers connected to this torrent. */
109                 private final int leechCount;
110
111                 /**
112                  * Creates a new torrent file.
113                  *
114                  * @param name
115                  *            The name of the file
116                  * @param size
117                  *            The size of the file
118                  * @param magnetUri
119                  *            The magnet URI of the file
120                  * @param downloadUri
121                  *            The download URI of the file
122                  * @param fileCount
123                  *            The number of files
124                  * @param seedCount
125                  *            The number of connected seeds
126                  * @param leechCount
127                  *            The number of connected leechers
128                  */
129                 public TorrentFile(String name, String size, String magnetUri, String downloadUri, int fileCount, int seedCount, int leechCount) {
130                         this.name = name;
131                         this.size = size;
132                         this.magnetUri = magnetUri;
133                         this.downloadUri = downloadUri;
134                         this.fileCount = fileCount;
135                         this.seedCount = seedCount;
136                         this.leechCount = leechCount;
137                 }
138
139                 //
140                 // ACCESSORS
141                 //
142
143                 /**
144                  * Returns the name of the file.
145                  *
146                  * @return The name of the file
147                  */
148                 public String name() {
149                         return name;
150                 }
151
152                 /**
153                  * Returns the size of the file. The returned size may included
154                  * non-numeric information, such as units (e. g. “860.46 MB”).
155                  *
156                  * @return The size of the file
157                  */
158                 public String size() {
159                         return size;
160                 }
161
162                 /**
163                  * Returns the magnet URI of the file.
164                  *
165                  * @return The magnet URI of the file
166                  */
167                 public String magnetUri() {
168                         return magnetUri;
169                 }
170
171                 /**
172                  * Returns the download URI of the file.
173                  *
174                  * @return The download URI of the file
175                  */
176                 public String downloadUri() {
177                         return downloadUri;
178                 }
179
180                 /**
181                  * Returns the number of files in this torrent.
182                  *
183                  * @return The number of files in this torrent
184                  */
185                 public int fileCount() {
186                         return fileCount;
187                 }
188
189                 /**
190                  * Returns the number of seeds connected to this torrent.
191                  *
192                  * @return The number of connected seeds
193                  */
194                 public int seedCount() {
195                         return seedCount;
196                 }
197
198                 /**
199                  * Returns the number of leechers connected to this torrent.
200                  *
201                  * @return The number of connected leechers
202                  */
203                 public int leechCount() {
204                         return leechCount;
205                 }
206
207                 //
208                 // PRIVATE METHODS
209                 //
210
211                 /**
212                  * Generates an ID for this file. If a {@link #magnetUri} is set, an ID
213                  * is {@link #extractId(String) extracted} from it. Otherwise the magnet
214                  * URI is used. If the {@link #magnetUri} is not set, the
215                  * {@link #downloadUri} is used. If that is not set either, the name of
216                  * the file is returned.
217                  *
218                  * @return The generated ID
219                  */
220                 private String generateId() {
221                         if (magnetUri != null) {
222                                 String id = extractId(magnetUri);
223                                 if (id != null) {
224                                         return id;
225                                 }
226                                 return magnetUri;
227                         }
228                         return (downloadUri != null) ? downloadUri : name;
229                 }
230
231                 //
232                 // STATIC METHODS
233                 //
234
235                 /**
236                  * Tries to extract the “exact target” of a magnet URI.
237                  *
238                  * @param magnetUri
239                  *            The magnet URI to extract the “xt” from
240                  * @return The extracted ID, or {@code null} if no ID could be found
241                  */
242                 private static String extractId(String magnetUri) {
243                         List<NameValuePair> parameters = URLEncodedUtils.parse(magnetUri.substring("magnet:?".length()), Charset.forName("UTF-8"));
244                         for (NameValuePair parameter : parameters) {
245                                 if (parameter.getName().equals("xt")) {
246                                         return parameter.getValue();
247                                 }
248                         }
249                         return null;
250                 }
251
252                 //
253                 // OBJECT METHODS
254                 //
255
256                 /**
257                  * {@inheritDoc}
258                  */
259                 @Override
260                 public int hashCode() {
261                         return (generateId() != null) ? generateId().hashCode() : 0;
262                 }
263
264                 /**
265                  * {@inheritDoc}
266                  */
267                 @Override
268                 public boolean equals(Object object) {
269                         if (!(object instanceof TorrentFile)) {
270                                 return false;
271                         }
272                         if (generateId() != null) {
273                                 return generateId().equals(((TorrentFile) object).generateId());
274                         }
275                         return false;
276                 }
277
278                 /**
279                  * {@inheritDoc}
280                  */
281                 @Override
282                 public String toString() {
283                         return String.format("%s(%s,%s,%s)", name(), size(), magnetUri(), downloadUri());
284                 }
285
286         }
287
288 }