/*
* Copyright (c) 2004-2016 Stuart Boston
*
* This file is part of the TVRage API.
*
* TVRage API 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
* any later version.
*
* TVRage API 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 TVRage API. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.omertron.tvrageapi.tools;
import com.omertron.tvrageapi.TVRageApi;
import com.omertron.tvrageapi.TVRageException;
import com.omertron.tvrageapi.model.CountryDetail;
import com.omertron.tvrageapi.model.Episode;
import com.omertron.tvrageapi.model.EpisodeList;
import com.omertron.tvrageapi.model.EpisodeNumber;
import com.omertron.tvrageapi.model.ShowInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class TVRageParser {
// Literals
private static final String EPISODE = "episode";
private static final String SUMMARY = "summary";
private static final String TITLE = "title";
private static final String AIRDATE = "airdate";
private static final String COUNTRY = "country";
// Constants
private static final int MATCH_SEASON = 1;
private static final int MATCH_EPISODE = 2;
// Hide the constructor
protected TVRageParser() {
// prevents calls from subclass
throw new UnsupportedOperationException();
}
private static Document getDocFromUrl(String searchUrl) throws TVRageException {
return DOMHelper.getEventDocFromUrl(searchUrl);
}
public static Episode getEpisodeInfo(String searchUrl) throws TVRageException {
Episode episode = new Episode();
Document doc = getDocFromUrl(searchUrl);
// The EpisodeInfo contains show information as well, but we will skip this
NodeList nlEpisode = doc.getElementsByTagName(EPISODE);
if (nlEpisode == null || nlEpisode.getLength() == 0) {
return episode;
}
// There's only one episode in the EpisodeInfo node
Element eEpisode = (Element) nlEpisode.item(0);
episode = parseEpisodeInfo(eEpisode);
return episode;
}
public static EpisodeList getEpisodeList(String searchUrl) throws TVRageException {
EpisodeList epList = new EpisodeList();
Document doc = getDocFromUrl(searchUrl);
NodeList nlEpisodeList;
Node nEpisodeList;
Element eEpisodeList;
nlEpisodeList = doc.getElementsByTagName("Show");
if (nlEpisodeList == null || nlEpisodeList.getLength() == 0) {
return epList;
}
// Get the show name and total seasons
for (int loop = 0; loop < nlEpisodeList.getLength(); loop++) {
nEpisodeList = nlEpisodeList.item(loop);
if (nEpisodeList.getNodeType() == Node.ELEMENT_NODE) {
eEpisodeList = (Element) nEpisodeList;
epList.setShowName(DOMHelper.getValueFromElement(eEpisodeList, "name"));
epList.setTotalSeasons(DOMHelper.getValueFromElement(eEpisodeList, "totalseasons"));
}
}
// Now process the individual seasons
processSeasons(epList, doc.getElementsByTagName("Season"));
return epList;
}
/**
* process the individual seasons
*
* @param epList
* @param nlSeasons
*/
private static void processSeasons(EpisodeList epList, NodeList nlSeasons) {
if (nlSeasons == null || nlSeasons.getLength() == 0) {
return;
}
Node nEpisodeList;
for (int loop = 0; loop < nlSeasons.getLength(); loop++) {
nEpisodeList = nlSeasons.item(loop);
if (nEpisodeList.getNodeType() == Node.ELEMENT_NODE) {
processSeasonEpisodes((Element) nEpisodeList, epList);
}
}
}
/**
* Process the episodes in the season and add them to the EpisodeList
*
* @param eEpisodeList
* @param epList
* @return
*/
private static void processSeasonEpisodes(Element eEpisodeList, EpisodeList epList) {
// Get the season number
String season = eEpisodeList.getAttribute("no");
NodeList nlEpisode = eEpisodeList.getElementsByTagName(EPISODE);
if (nlEpisode == null || nlEpisode.getLength() == 0) {
return;
}
for (int eLoop = 0; eLoop < nlEpisode.getLength(); eLoop++) {
Node nEpisode = nlEpisode.item(eLoop);
if (nEpisode.getNodeType() == Node.ELEMENT_NODE) {
epList.addEpisode(parseEpisode((Element) nEpisode, season));
}
}
}
public static List<ShowInfo> getSearchShow(String searchUrl) throws TVRageException {
return processShowInfo(searchUrl, "show");
}
public static List<ShowInfo> getShowInfo(String searchUrl) throws TVRageException {
return processShowInfo(searchUrl, "Showinfo");
}
/**
* Get a list of the ShowInfo from the specified tag
*
* @param searchUrl
* @param tagName
* @return
*/
private static List<ShowInfo> processShowInfo(String searchUrl, String tagName) throws TVRageException {
List<ShowInfo> showList = new ArrayList<>();
ShowInfo showInfo;
Document doc = getDocFromUrl(searchUrl);
NodeList nlShowInfo = doc.getElementsByTagName(tagName);
if (nlShowInfo == null || nlShowInfo.getLength() == 0) {
return showList;
}
for (int loop = 0; loop < nlShowInfo.getLength(); loop++) {
Node nShowInfo = nlShowInfo.item(loop);
if (nShowInfo.getNodeType() == Node.ELEMENT_NODE) {
Element eShowInfo = (Element) nShowInfo;
showInfo = parseNextShowInfo(eShowInfo);
showList.add(showInfo);
}
}
return showList;
}
/**
* Parse the episode node into an Episode object
*
* @param eEpisode
* @param season
* @return
*/
private static Episode parseEpisode(Element eEpisode, String season) {
Episode episode = new Episode();
EpisodeNumber en = new EpisodeNumber();
en.setSeason(season);
en.setEpisode(DOMHelper.getValueFromElement(eEpisode, "seasonnum"));
en.setAbsolute(DOMHelper.getValueFromElement(eEpisode, "epnum"));
episode.setEpisodeNumber(en);
episode.setProductionId(DOMHelper.getValueFromElement(eEpisode, "prodnum"));
episode.setAirDate(DOMHelper.getValueFromElement(eEpisode, AIRDATE));
episode.setLink(DOMHelper.getValueFromElement(eEpisode, "link"));
episode.setTitle(DOMHelper.getValueFromElement(eEpisode, TITLE));
episode.setSummary(DOMHelper.getValueFromElement(eEpisode, SUMMARY));
episode.setRating(DOMHelper.getValueFromElement(eEpisode, "rating"));
episode.setScreenCap(DOMHelper.getValueFromElement(eEpisode, "screencap"));
return episode;
}
/**
* Parse the episode info node into an Episode object
*
* @param eEpisodeInfo
* @return
*/
private static Episode parseEpisodeInfo(Element eEpisodeInfo) {
Episode episode = new Episode();
episode.setTitle(DOMHelper.getValueFromElement(eEpisodeInfo, TITLE));
episode.setAirDate(DOMHelper.getValueFromElement(eEpisodeInfo, AIRDATE));
episode.setLink(DOMHelper.getValueFromElement(eEpisodeInfo, "url"));
episode.setSummary(DOMHelper.getValueFromElement(eEpisodeInfo, SUMMARY));
// Process the season & episode field
Pattern pattern = Pattern.compile("(\\d*)[x](\\d*)");
Matcher matcher = pattern.matcher(DOMHelper.getValueFromElement(eEpisodeInfo, "number"));
if (matcher.find()) {
EpisodeNumber en = new EpisodeNumber();
en.setSeason(matcher.group(MATCH_SEASON));
en.setEpisode(matcher.group(MATCH_EPISODE));
episode.setEpisodeNumber(en);
}
return episode;
}
/**
* Parse the show info element into a ShowInfo object
*
* @param eShowInfo
* @return
*/
private static ShowInfo parseNextShowInfo(Element eShowInfo) {
ShowInfo showInfo = new ShowInfo();
String text;
// ShowID
showInfo.setShowID(DOMHelper.getValueFromElement(eShowInfo, "showid"));
// ShowName
text = DOMHelper.getValueFromElement(eShowInfo, "showname");
if (!TVRageApi.isValidString(text)) {
text = DOMHelper.getValueFromElement(eShowInfo, "name");
}
showInfo.setShowName(text);
// ShowLink
text = DOMHelper.getValueFromElement(eShowInfo, "showlink");
if (!TVRageApi.isValidString(text)) {
text = DOMHelper.getValueFromElement(eShowInfo, "link");
}
showInfo.setShowLink(text);
// Country
text = DOMHelper.getValueFromElement(eShowInfo, COUNTRY);
if (!TVRageApi.isValidString(text)) {
text = DOMHelper.getValueFromElement(eShowInfo, "origin_country");
}
showInfo.setCountry(text);
// Started
showInfo.setStarted(DOMHelper.getValueFromElement(eShowInfo, "started"));
// StartDate
showInfo.setStartDate(DOMHelper.getValueFromElement(eShowInfo, "startdate"));
// Ended
showInfo.setEnded(DOMHelper.getValueFromElement(eShowInfo, "ended"));
// Seasons
showInfo.setTotalSeasons(DOMHelper.getValueFromElement(eShowInfo, "seasons"));
// Status
showInfo.setStatus(DOMHelper.getValueFromElement(eShowInfo, "status"));
// Classification
showInfo.setClassification(DOMHelper.getValueFromElement(eShowInfo, "classification"));
// Summary
showInfo.setSummary(DOMHelper.getValueFromElement(eShowInfo, SUMMARY));
// Runtime
showInfo.setRuntime(DOMHelper.getValueFromElement(eShowInfo, "runtime"));
// Air Time
showInfo.setAirTime(DOMHelper.getValueFromElement(eShowInfo, "airtime"));
// Air Day
showInfo.setAirDay(DOMHelper.getValueFromElement(eShowInfo, "airday"));
// Time Zone
showInfo.setTimezone(DOMHelper.getValueFromElement(eShowInfo, "timezone"));
// Network
processNetwork(showInfo, eShowInfo);
// AKAs
processAka(showInfo, eShowInfo);
// Genres
processGenre(showInfo, eShowInfo);
return showInfo;
}
/**
* Process network information
*
* @param showInfo
* @param eShowInfo
*/
private static void processNetwork(ShowInfo showInfo, Element eShowInfo) {
NodeList nlNetwork = eShowInfo.getElementsByTagName("network");
for (int nodeLoop = 0; nodeLoop < nlNetwork.getLength(); nodeLoop++) {
Node nShowInfo = nlNetwork.item(nodeLoop);
if (nShowInfo.getNodeType() == Node.ELEMENT_NODE) {
Element eNetwork = (Element) nShowInfo;
CountryDetail newNetwork = new CountryDetail();
newNetwork.setCountry(eNetwork.getAttribute(COUNTRY));
newNetwork.setDetail(eNetwork.getTextContent());
showInfo.addNetwork(newNetwork);
}
}
}
/**
* Process AKA information
*
* @param showInfo
* @param eShowInfo
*/
private static void processAka(ShowInfo showInfo, Element eShowInfo) {
NodeList nlAkas = eShowInfo.getElementsByTagName("aka");
for (int loop = 0; loop < nlAkas.getLength(); loop++) {
Node nShowInfo = nlAkas.item(loop);
if (nShowInfo.getNodeType() == Node.ELEMENT_NODE) {
Element eAka = (Element) nShowInfo;
CountryDetail newAka = new CountryDetail();
newAka.setCountry(eAka.getAttribute(COUNTRY));
newAka.setDetail(eAka.getTextContent());
showInfo.addAka(newAka);
}
}
}
/**
* Process Genres
*
* @param showInfo
* @param eShowInfo
*/
private static void processGenre(ShowInfo showInfo, Element eShowInfo) {
NodeList nlGenres = eShowInfo.getElementsByTagName("genre");
for (int loop = 0; loop < nlGenres.getLength(); loop++) {
Node nGenre = nlGenres.item(loop);
if (nGenre.getNodeType() == Node.ELEMENT_NODE) {
Element eGenre = (Element) nGenre;
if (eGenre.getFirstChild() != null) {
showInfo.addGenre(eGenre.getFirstChild().getNodeValue());
}
}
}
}
}