78ca478204bce65728abe448819f559296617610
[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         @Override
69         public boolean isEmpty() {
70                 return episodes.isEmpty();
71         }
72
73         /**
74          * Returns all episodes contained in this state.
75          *
76          * @return The episodes of this state
77          */
78         public Collection<Episode> episodes() {
79                 return Collections.unmodifiableCollection(episodes);
80         }
81
82         //
83         // ITERABLE INTERFACE
84         //
85
86         /**
87          * {@inheritDoc}
88          */
89         @Override
90         public Iterator<Episode> iterator() {
91                 return episodes.iterator();
92         }
93
94         /**
95          * {@inheritDoc}
96          */
97         @Override
98         public String toString() {
99                 return String.format("%s[episodes=%s]", getClass().getSimpleName(), episodes);
100         }
101
102         /**
103          * Stores attributes for an episode.
104          *
105          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
106          */
107         public static class Episode implements Comparable<Episode>, Iterable<TorrentFile> {
108
109                 /** Function to extract the season of an episode. */
110                 public static final Function<Episode, Integer> BY_SEASON = new Function<Episode, Integer>() {
111
112                         @Override
113                         public Integer apply(Episode episode) {
114                                 return (episode != null ) ? episode.season() : -1;
115                         }
116                 };
117
118                 /** The season of the episode. */
119                 @JsonProperty
120                 private final int season;
121
122                 /** The number of the episode. */
123                 @JsonProperty
124                 private final int episode;
125
126                 /** The torrent files for this episode. */
127                 @JsonProperty
128                 private final List<TorrentFile> torrentFiles = new ArrayList<TorrentFile>();
129
130                 /**
131                  * No-arg constructor for deserialization.
132                  */
133                 @SuppressWarnings("unused")
134                 private Episode() {
135                         this(0, 0);
136                 }
137
138                 /**
139                  * Creates a new episode.
140                  *
141                  * @param season
142                  *            The season of the episode
143                  * @param episode
144                  *            The number of the episode
145                  */
146                 public Episode(int season, int episode) {
147                         this.season = season;
148                         this.episode = episode;
149                 }
150
151                 //
152                 // ACCESSORS
153                 //
154
155                 /**
156                  * Returns the season of this episode.
157                  *
158                  * @return The season of this episode
159                  */
160                 public int season() {
161                         return season;
162                 }
163
164                 /**
165                  * Returns the number of this episode.
166                  *
167                  * @return The number of this episode
168                  */
169                 public int episode() {
170                         return episode;
171                 }
172
173                 /**
174                  * Returns the torrent files of this episode.
175                  *
176                  * @return The torrent files of this episode
177                  */
178                 public Collection<TorrentFile> torrentFiles() {
179                         return torrentFiles;
180                 }
181
182                 /**
183                  * Returns the identifier of this episode.
184                  *
185                  * @return The identifier of this episode
186                  */
187                 public String identifier() {
188                         return String.format("S%02dE%02d", season, episode);
189                 }
190
191                 //
192                 // ACTIONS
193                 //
194
195                 /**
196                  * Adds the given torrent file to this episode.
197                  *
198                  * @param torrentFile
199                  *            The torrent file to add
200                  */
201                 public void addTorrentFile(TorrentFile torrentFile) {
202                         if (!torrentFiles.contains(torrentFile)) {
203                                 torrentFiles.add(torrentFile);
204                         }
205                 }
206
207                 //
208                 // ITERABLE METHODS
209                 //
210
211                 /**
212                  * {@inheritDoc}
213                  */
214                 @Override
215                 public Iterator<TorrentFile> iterator() {
216                         return torrentFiles.iterator();
217                 }
218
219                 /**
220                  * {@inheritDoc}
221                  */
222                 @Override
223                 public int compareTo(Episode episode) {
224                         if (season() < episode.season()) {
225                                 return -1;
226                         }
227                         if (season() > episode.season()) {
228                                 return 1;
229                         }
230                         if (episode() < episode.episode()) {
231                                 return -1;
232                         }
233                         if (episode() > episode.episode()) {
234                                 return 1;
235                         }
236                         return 0;
237                 }
238
239                 //
240                 // OBJECT METHODS
241                 //
242
243                 /**
244                  * {@inheritDoc}
245                  */
246                 @Override
247                 public int hashCode() {
248                         return season * 65536 + episode;
249                 }
250
251                 /**
252                  * {@inheritDoc}
253                  */
254                 @Override
255                 public boolean equals(Object obj) {
256                         if (!(obj instanceof Episode)) {
257                                 return false;
258                         }
259                         Episode episode = (Episode) obj;
260                         return (season == episode.season) && (this.episode == episode.episode);
261                 }
262
263                 /**
264                  * {@inheritDoc}
265                  */
266                 @Override
267                 public String toString() {
268                         return String.format("%s[season=%d,episode=%d,torrentFiles=%s]", getClass().getSimpleName(), season, episode, torrentFiles);
269                 }
270
271         }
272
273 }