001package net.filebot.web; 002 003import static java.util.Arrays.*; 004import static java.util.Collections.*; 005import static net.filebot.web.WebRequest.*; 006 007import java.io.Serializable; 008import java.net.URL; 009import java.time.Instant; 010import java.time.LocalDate; 011import java.util.List; 012import java.util.Locale; 013import java.util.Map; 014import java.util.stream.Stream; 015 016public class SeriesDetails extends SeriesInfo implements Serializable { 017 018 // common properties 019 protected String overview; 020 protected String poster; 021 022 protected String originalName; 023 protected String originalLanguage; 024 protected String[] country; 025 026 // TheMovieDB properties 027 protected int[] seasons; 028 protected Double popularity; 029 protected SimpleDate endDate; 030 protected Map<String, String> certifications; 031 protected String[] keywords; 032 033 // TheTVDB properties 034 protected String slug; 035 protected Integer imdbId; 036 protected String[] airsDays; 037 protected String airsTime; 038 protected Instant lastUpdated; 039 040 public SeriesDetails() { 041 // used by deserializer 042 } 043 044 public SeriesDetails(SeriesDetails other) { 045 super(other); 046 047 this.overview = other.overview; 048 this.poster = other.poster; 049 this.originalName = other.originalName; 050 this.originalLanguage = other.originalLanguage; 051 this.country = other.country; 052 053 this.seasons = other.seasons; 054 this.popularity = other.popularity; 055 this.endDate = other.endDate; 056 this.certifications = other.certifications; 057 058 this.slug = other.slug; 059 this.imdbId = other.imdbId; 060 this.overview = other.overview; 061 this.airsDays = other.airsDays; 062 this.airsTime = other.airsTime; 063 this.lastUpdated = other.lastUpdated; 064 } 065 066 public SeriesDetails(Datasource database, SortOrder order, Locale language, Integer id, String type) { 067 super(database, order, language, id, type); 068 } 069 070 // common properties 071 072 public String getOverview() { 073 return overview; 074 } 075 076 public void setOverview(String overview) { 077 this.overview = overview; 078 } 079 080 public void setPoster(URL poster) { 081 this.poster = poster == null ? null : poster.toExternalForm(); 082 } 083 084 public URL getPoster() { 085 return parseURL(poster); 086 } 087 088 public String getOriginalName() { 089 return originalName; 090 } 091 092 public void setOriginalName(String originalName) { 093 this.originalName = originalName; 094 } 095 096 public String getOriginalLanguage() { 097 return originalLanguage; 098 } 099 100 public void setOriginalLanguage(String originalLanguage) { 101 this.originalLanguage = originalLanguage; 102 } 103 104 public List<String> getCountry() { 105 return country == null || country.length == 0 ? emptyList() : unmodifiableList(asList(country)); 106 } 107 108 public void setCountry(String[] country) { 109 this.country = country; 110 } 111 112 // TheMovieDB properties 113 114 public int[] getSeasons() { 115 return seasons.clone(); 116 } 117 118 public void setSeasons(int[] seasons) { 119 this.seasons = seasons; 120 } 121 122 public Double getPopularity() { 123 return popularity; 124 } 125 126 public void setPopularity(Double popularity) { 127 this.popularity = popularity; 128 } 129 130 public SimpleDate getEndDate() { 131 return endDate; 132 } 133 134 public void setEndDate(SimpleDate endDate) { 135 this.endDate = endDate; 136 } 137 138 public Map<String, String> getCertifications() { 139 return certifications == null || certifications.isEmpty() ? emptyMap() : unmodifiableMap(certifications); 140 } 141 142 public void setCertifications(Map<String, String> certifications) { 143 this.certifications = certifications; 144 } 145 146 public List<String> getKeywords() { 147 return keywords == null || keywords.length == 0 ? emptyList() : unmodifiableList(asList(keywords)); 148 } 149 150 public void setKeywords(String[] keywords) { 151 this.keywords = keywords; 152 } 153 154 // TheTVDB properties 155 156 public String getSlug() { 157 return slug; 158 } 159 160 public void setSlug(String slug) { 161 this.slug = slug; 162 } 163 164 public Integer getImdbId() { 165 return imdbId; 166 } 167 168 public void setImdbId(Integer imdbId) { 169 this.imdbId = imdbId; 170 } 171 172 public List<String> getAirsDays() { 173 return airsDays == null || airsDays.length == 0 ? emptyList() : unmodifiableList(asList(airsDays)); 174 } 175 176 public void setAirsDays(String[] airsDays) { 177 this.airsDays = airsDays; 178 } 179 180 public String getAirsTime() { 181 return airsTime; 182 } 183 184 public void setAirsTime(String airsTime) { 185 this.airsTime = airsTime; 186 } 187 188 public Instant getLastUpdated() { 189 return lastUpdated; 190 } 191 192 public void setLastUpdated(Instant lastUpdated) { 193 this.lastUpdated = lastUpdated; 194 } 195 196 public boolean hasEnded() { 197 // using TheMovieDB properties 198 return "Ended".equalsIgnoreCase(status); 199 } 200 201 public boolean isContinuing() { 202 // using TheTVDB properties 203 return "Continuing".equalsIgnoreCase(status); 204 } 205 206 public boolean isRecent() { 207 // using TheMovieDB properties 208 if (endDate != null && endDate.toLocalDate().until(LocalDate.now()).toTotalMonths() < 2) { 209 return true; 210 } 211 // using TheTVDB properties (or TheMovieDB properties if end date is undefined) 212 if (startDate != null && startDate.toLocalDate().plusYears(seasons == null ? 0 : seasons.length - 1).until(LocalDate.now()).toTotalMonths() < 6) { 213 return true; 214 } 215 return false; 216 } 217 218 public boolean isAiringToday() { 219 // using TheTVDBv2 properties 220 if (airsDays != null && stream(airsDays).anyMatch("Weekdays"::equalsIgnoreCase)) { 221 return true; 222 } 223 // using TheTVDBv4 / TheTVDBv2 properties 224 if (airsDays != null && Stream.of(LocalDate.now(), LocalDate.now().minusDays(1)).anyMatch(d -> stream(airsDays).anyMatch(d.getDayOfWeek().name()::equalsIgnoreCase))) { 225 return true; 226 } 227 return false; 228 } 229 230 @Override 231 public SeriesDetails clone() { 232 return new SeriesDetails(this); 233 } 234 235}