Only add the torrent if it doesn’t already exist.
[rhynodge.git] / src / main / java / net / pterodactylus / rhynodge / states / EpisodeState.java
1 /*
2  * Rhynodge - EpisodeState.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.rhynodge.states;
19
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.Iterator;
24 import java.util.List;
25
26 import net.pterodactylus.rhynodge.State;
27 import net.pterodactylus.rhynodge.filters.EpisodeFilter;
28 import net.pterodactylus.rhynodge.states.EpisodeState.Episode;
29 import net.pterodactylus.rhynodge.states.TorrentState.TorrentFile;
30
31 import com.fasterxml.jackson.annotation.JsonProperty;
32 import com.google.common.base.Function;
33
34 /**
35  * {@link State} implementation that stores episodes of TV shows, parsed via
36  * {@link EpisodeFilter} from a previous {@link TorrentState}.
37  *
38  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
39  */
40 public class EpisodeState extends AbstractState implements Iterable<Episode> {
41
42         /** The episodes found in the current request. */
43         @JsonProperty
44         private final List<Episode> episodes = new ArrayList<Episode>();
45
46         /**
47          * No-arg constructor for deserialization.
48          */
49         @SuppressWarnings("unused")
50         private EpisodeState() {
51                 this(Collections.<Episode> emptySet());
52         }
53
54         /**
55          * Creates a new episode state.
56          *
57          * @param episodes
58          *            The episodes of the request
59          */
60         public EpisodeState(Collection<Episode> episodes) {
61                 this.episodes.addAll(episodes);
62         }
63
64         //
65         // ACCESSORS
66         //
67
68         /**
69          * Returns all episodes contained in this state.
70          *
71          * @return The episodes of this state
72          */
73         public Collection<Episode> episodes() {
74                 return Collections.unmodifiableCollection(episodes);
75         }
76
77         //
78         // ITERABLE INTERFACE
79         //
80
81         /**
82          * {@inheritDoc}
83          */
84         @Override
85         public Iterator<Episode> iterator() {
86                 return episodes.iterator();
87         }
88
89         /**
90          * {@inheritDoc}
91          */
92         @Override
93         public String toString() {
94                 return String.format("%s[episodes=%s]", getClass().getSimpleName(), episodes);
95         }
96
97         /**
98          * Stores attributes for an episode.
99          *
100          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
101          */
102         public static class Episode implements Comparable<Episode>, Iterable<TorrentFile> {
103
104                 /** Function to extract the season of an episode. */
105                 public static final Function<Episode, Integer> BY_SEASON = new Function<Episode, Integer>() {
106
107                         @Override
108                         public Integer apply(Episode episode) {
109                                 return episode.season();
110                         }
111                 };
112
113                 /** The season of the episode. */
114                 @JsonProperty
115                 private final int season;
116
117                 /** The number of the episode. */
118                 @JsonProperty
119                 private final int episode;
120
121                 /** The torrent files for this episode. */
122                 @JsonProperty
123                 private final List<TorrentFile> torrentFiles = new ArrayList<TorrentFile>();
124
125                 /**
126                  * No-arg constructor for deserialization.
127                  */
128                 @SuppressWarnings("unused")
129                 private Episode() {
130                         this(0, 0);
131                 }
132
133                 /**
134                  * Creates a new episode.
135                  *
136                  * @param season
137                  *            The season of the episode
138                  * @param episode
139                  *            The number of the episode
140                  */
141                 public Episode(int season, int episode) {
142                         this.season = season;
143                         this.episode = episode;
144                 }
145
146                 //
147                 // ACCESSORS
148                 //
149
150                 /**
151                  * Returns the season of this episode.
152                  *
153                  * @return The season of this episode
154                  */
155                 public int season() {
156                         return season;
157                 }
158
159                 /**
160                  * Returns the number of this episode.
161                  *
162                  * @return The number of this episode
163                  */
164                 public int episode() {
165                         return episode;
166                 }
167
168                 /**
169                  * Returns the torrent files of this episode.
170                  *
171                  * @return The torrent files of this episode
172                  */
173                 public Collection<TorrentFile> torrentFiles() {
174                         return torrentFiles;
175                 }
176
177                 /**
178                  * Returns the identifier of this episode.
179                  *
180                  * @return The identifier of this episode
181                  */
182                 public String identifier() {
183                         return String.format("S%02dE%02d", season, episode);
184                 }
185
186                 //
187                 // ACTIONS
188                 //
189
190                 /**
191                  * Adds the given torrent file to this episode.
192                  *
193                  * @param torrentFile
194                  *            The torrent file to add
195                  */
196                 public void addTorrentFile(TorrentFile torrentFile) {
197                         if (!torrentFiles.contains(torrentFile)) {
198                                 torrentFiles.add(torrentFile);
199                         }
200                 }
201
202                 //
203                 // ITERABLE METHODS
204                 //
205
206                 /**
207                  * {@inheritDoc}
208                  */
209                 @Override
210                 public Iterator<TorrentFile> iterator() {
211                         return torrentFiles.iterator();
212                 }
213
214                 /**
215                  * {@inheritDoc}
216                  */
217                 @Override
218                 public int compareTo(Episode episode) {
219                         if (season() < episode.season()) {
220                                 return -1;
221                         }
222                         if (season() > episode.season()) {
223                                 return 1;
224                         }
225                         if (episode() < episode.episode()) {
226                                 return -1;
227                         }
228                         if (episode() > episode.episode()) {
229                                 return 1;
230                         }
231                         return 0;
232                 }
233
234                 //
235                 // OBJECT METHODS
236                 //
237
238                 /**
239                  * {@inheritDoc}
240                  */
241                 @Override
242                 public int hashCode() {
243                         return season * 65536 + episode;
244                 }
245
246                 /**
247                  * {@inheritDoc}
248                  */
249                 @Override
250                 public boolean equals(Object obj) {
251                         if (!(obj instanceof Episode)) {
252                                 return false;
253                         }
254                         Episode episode = (Episode) obj;
255                         return (season == episode.season) && (this.episode == episode.episode);
256                 }
257
258                 /**
259                  * {@inheritDoc}
260                  */
261                 @Override
262                 public String toString() {
263                         return String.format("%s[season=%d,episode=%d,torrentFiles=%s]", getClass().getSimpleName(), season, episode, torrentFiles);
264                 }
265
266         }
267
268 }