0855195226f98d5f9153ee92761e02a6a72f6dc9
[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                 /**
103                  * Creates a new torrent file.
104                  *
105                  * @param name
106                  *            The name of the file
107                  * @param size
108                  *            The size of the file
109                  * @param magnetUri
110                  *            The magnet URI of the file
111                  * @param downloadUri
112                  *            The download URI of the file
113                  */
114                 public TorrentFile(String name, String size, String magnetUri, String downloadUri) {
115                         this.name = name;
116                         this.size = size;
117                         this.magnetUri = magnetUri;
118                         this.downloadUri = downloadUri;
119                 }
120
121                 //
122                 // ACCESSORS
123                 //
124
125                 /**
126                  * Returns the name of the file.
127                  *
128                  * @return The name of the file
129                  */
130                 public String name() {
131                         return name;
132                 }
133
134                 /**
135                  * Returns the size of the file. The returned size may included
136                  * non-numeric information, such as units (e. g. “860.46 MB”).
137                  *
138                  * @return The size of the file
139                  */
140                 public String size() {
141                         return size;
142                 }
143
144                 /**
145                  * Returns the magnet URI of the file.
146                  *
147                  * @return The magnet URI of the file
148                  */
149                 public String magnetUri() {
150                         return magnetUri;
151                 }
152
153                 /**
154                  * Returns the download URI of the file.
155                  *
156                  * @return The download URI of the file
157                  */
158                 public String downloadUri() {
159                         return downloadUri;
160                 }
161
162                 //
163                 // PRIVATE METHODS
164                 //
165
166                 /**
167                  * Generates an ID for this file. If a {@link #magnetUri} is set, an ID
168                  * is {@link #extractId(String) extracted} from it. Otherwise the magnet
169                  * URI is used. If the {@link #magnetUri} is not set, the
170                  * {@link #downloadUri} is used. If that is not set either, the name of
171                  * the file is returned.
172                  *
173                  * @return The generated ID
174                  */
175                 private String generateId() {
176                         if (magnetUri != null) {
177                                 String id = extractId(magnetUri);
178                                 if (id != null) {
179                                         return id;
180                                 }
181                                 return magnetUri;
182                         }
183                         return (downloadUri != null) ? downloadUri : name;
184                 }
185
186                 //
187                 // STATIC METHODS
188                 //
189
190                 /**
191                  * Tries to extract the “exact target” of a magnet URI.
192                  *
193                  * @param magnetUri
194                  *            The magnet URI to extract the “xt” from
195                  * @return The extracted ID, or {@code null} if no ID could be found
196                  */
197                 private static String extractId(String magnetUri) {
198                         List<NameValuePair> parameters = URLEncodedUtils.parse(magnetUri.substring("magnet:?".length()), Charset.forName("UTF-8"));
199                         for (NameValuePair parameter : parameters) {
200                                 if (parameter.getName().equals("xt")) {
201                                         return parameter.getValue();
202                                 }
203                         }
204                         return null;
205                 }
206
207                 //
208                 // OBJECT METHODS
209                 //
210
211                 /**
212                  * {@inheritDoc}
213                  */
214                 @Override
215                 public int hashCode() {
216                         return (generateId() != null) ? generateId().hashCode() : 0;
217                 }
218
219                 /**
220                  * {@inheritDoc}
221                  */
222                 @Override
223                 public boolean equals(Object object) {
224                         if (!(object instanceof TorrentFile)) {
225                                 return false;
226                         }
227                         if (generateId() != null) {
228                                 return generateId().equals(((TorrentFile) object).generateId());
229                         }
230                         return false;
231                 }
232
233                 /**
234                  * {@inheritDoc}
235                  */
236                 @Override
237                 public String toString() {
238                         return String.format("%s(%s,%s,%s)", name(), size(), magnetUri(), downloadUri());
239                 }
240
241         }
242
243 }