Rename project to “Rhynodge.”
[rhynodge.git] / src / main / java / net / pterodactylus / rhynodge / filters / EpisodeFilter.java
diff --git a/src/main/java/net/pterodactylus/rhynodge/filters/EpisodeFilter.java b/src/main/java/net/pterodactylus/rhynodge/filters/EpisodeFilter.java
new file mode 100644 (file)
index 0000000..91fe098
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Rhynodge - EpisodeFilter.java - Copyright © 2013 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.rhynodge.filters;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.LinkedHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import net.pterodactylus.rhynodge.Filter;
+import net.pterodactylus.rhynodge.State;
+import net.pterodactylus.rhynodge.states.EpisodeState;
+import net.pterodactylus.rhynodge.states.EpisodeState.Episode;
+import net.pterodactylus.rhynodge.states.FailedState;
+import net.pterodactylus.rhynodge.states.TorrentState;
+import net.pterodactylus.rhynodge.states.TorrentState.TorrentFile;
+
+/**
+ * {@link Filter} implementation that extracts {@link Episode} information from
+ * the {@link TorrentFile}s contained in a {@link TorrentState}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class EpisodeFilter implements Filter {
+
+       /** The pattern to parse episode information from the filename. */
+       private static Pattern episodePattern = Pattern.compile("S(\\d{2})E(\\d{2})|[^\\d](\\d{1,2})x(\\d{2})[^\\d]");
+
+       //
+       // FILTER METHODS
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public State filter(State state) {
+               if (!state.success()) {
+                       return FailedState.from(state);
+               }
+               checkState(state instanceof TorrentState, "state is not a TorrentState but a %s!", state.getClass());
+
+               TorrentState torrentState = (TorrentState) state;
+               LinkedHashMap<Episode, Episode> episodes = new LinkedHashMap<Episode, Episode>();
+               for (TorrentFile torrentFile : torrentState) {
+                       Episode episode = extractEpisode(torrentFile);
+                       if (episode == null) {
+                               continue;
+                       }
+                       episodes.put(episode, episode);
+                       episode = episodes.get(episode);
+                       episode.addTorrentFile(torrentFile);
+               }
+
+               return new EpisodeState(episodes.values());
+       }
+
+       //
+       // STATIC METHODS
+       //
+
+       /**
+        * Extracts episode information from the given torrent file.
+        *
+        * @param torrentFile
+        *            The torrent file to extract the episode information from
+        * @return The extracted episode information, or {@code null} if no episode
+        *         information could be found
+        */
+       private static Episode extractEpisode(TorrentFile torrentFile) {
+               Matcher matcher = episodePattern.matcher(torrentFile.name());
+               if (!matcher.find()) {
+                       return null;
+               }
+               String seasonString = matcher.group(1);
+               String episodeString = matcher.group(2);
+               if ((seasonString == null) && (episodeString == null)) {
+                       seasonString = matcher.group(3);
+                       episodeString = matcher.group(4);
+               }
+               int season = Integer.valueOf(seasonString);
+               int episode = Integer.valueOf(episodeString);
+               return new Episode(season, episode);
+       }
+
+}