From be01e825891e7dbd24071ecb2d8bbd5ccba0133a Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Mon, 9 May 2016 22:59:21 +0800 Subject: [PATCH] Unify Actors/Cast/Crew API --- source/net/filebot/web/Artwork.java | 21 +-- source/net/filebot/web/FanartTVClient.java | 2 +- source/net/filebot/web/OMDbClient.java | 9 +- source/net/filebot/web/Person.java | 81 ++++++++++++ source/net/filebot/web/TMDbClient.java | 138 +++++++------------- source/net/filebot/web/TheTVDBClient.java | 37 +++--- test/net/filebot/web/TMDbClientTest.java | 29 ++-- test/net/filebot/web/TheTVDBClientTest.java | 35 +++-- 8 files changed, 202 insertions(+), 150 deletions(-) create mode 100644 source/net/filebot/web/Person.java diff --git a/source/net/filebot/web/Artwork.java b/source/net/filebot/web/Artwork.java index 148351cd..d62c8366 100644 --- a/source/net/filebot/web/Artwork.java +++ b/source/net/filebot/web/Artwork.java @@ -14,28 +14,21 @@ import java.util.stream.Stream; public class Artwork implements Serializable { - private String database; + protected String[] tags; + protected URL url; - private String[] tags; - private URL url; - - private String language; - private double rating; + protected String language; + protected Double rating; public Artwork() { // used by serializer } - public Artwork(Datasource database, Stream tags, URL url, Locale language, Double rating) { - this.database = database.getIdentifier(); + public Artwork(Stream tags, URL url, Locale language, Double rating) { this.tags = tags.filter(Objects::nonNull).map(Object::toString).toArray(String[]::new); this.url = url; this.language = language == null || language.getLanguage().isEmpty() ? null : language.getLanguage(); - this.rating = rating == null ? 0 : rating; - } - - public String getDatabase() { - return database; + this.rating = rating; } public List getTags() { @@ -51,7 +44,7 @@ public class Artwork implements Serializable { } public double getRating() { - return rating; + return rating == null ? 0 : rating; } public boolean matches(Object... tags) { diff --git a/source/net/filebot/web/FanartTVClient.java b/source/net/filebot/web/FanartTVClient.java index adcd96e7..f151a06a 100644 --- a/source/net/filebot/web/FanartTVClient.java +++ b/source/net/filebot/web/FanartTVClient.java @@ -53,7 +53,7 @@ public class FanartTVClient implements Datasource, ArtworkProvider { String season = getString(it, "season"); String discType = getString(it, "disc_type"); - return new Artwork(this, Stream.of(type.getKey(), season, discType), new URL(url), language, likes); + return new Artwork(Stream.of(type.getKey(), season, discType), new URL(url), language, likes); } catch (Exception e) { debug.log(Level.WARNING, e, e::getMessage); return null; diff --git a/source/net/filebot/web/OMDbClient.java b/source/net/filebot/web/OMDbClient.java index 7ec159a2..334a7e2d 100644 --- a/source/net/filebot/web/OMDbClient.java +++ b/source/net/filebot/web/OMDbClient.java @@ -32,8 +32,7 @@ import net.filebot.Cache; import net.filebot.CacheType; import net.filebot.ResourceManager; import net.filebot.web.TMDbClient.MovieInfo; -import net.filebot.web.TMDbClient.MovieInfo.MovieProperty; -import net.filebot.web.TMDbClient.Person; +import net.filebot.web.TMDbClient.MovieProperty; public class OMDbClient implements MovieIdentificationService { @@ -188,9 +187,9 @@ public class OMDbClient implements MovieIdentificationService { List languages = split(delim, data.get("language"), String::toString); List actors = new ArrayList(); - actors.addAll(split(delim, data.get("actors"), (s) -> new Person(s, null, null))); - actors.addAll(split(delim, data.get("director"), (s) -> new Person(s, null, "Director"))); - actors.addAll(split(delim, data.get("writer"), (s) -> new Person(s, null, "Writer"))); + actors.addAll(split(delim, data.get("actors"), (s) -> new Person(s, Person.ACTOR))); + actors.addAll(split(delim, data.get("director"), (s) -> new Person(s, Person.DIRECTOR))); + actors.addAll(split(delim, data.get("writer"), (s) -> new Person(s, Person.WRITER))); return new MovieInfo(fields, emptyList(), genres, emptyMap(), languages, emptyList(), emptyList(), actors, emptyList()); } diff --git a/source/net/filebot/web/Person.java b/source/net/filebot/web/Person.java new file mode 100644 index 00000000..0d2f6de9 --- /dev/null +++ b/source/net/filebot/web/Person.java @@ -0,0 +1,81 @@ +package net.filebot.web; + +import static java.util.Comparator.*; +import java.io.Serializable; +import java.net.URL; +import java.util.Comparator; + +public class Person implements Serializable { + + protected String name; + protected String character; + protected String job; + protected String department; + protected Integer order; + protected URL image; + + protected Person() { + // used by serializer + } + + public Person(String name, String job) { + this(name, null, job, null, null, null); + } + + public Person(String name, String character, String job, String department, Integer order, URL image) { + this.name = name; + this.character = character == null || character.isEmpty() ? null : character; + this.job = job == null || job.isEmpty() ? null : job; + this.department = department == null || department.isEmpty() ? null : department; + this.order = order; + this.image = image; + } + + public String getName() { + return name; + } + + public String getCharacter() { + return character; + } + + public String getJob() { + return job; + } + + public String getDepartment() { + return department; + } + + public Integer getOrder() { + return order; + } + + public URL getImage() { + return image; + } + + public boolean isActor() { + return character != null || ACTOR.equals(getJob()); + } + + public boolean isDirector() { + return DIRECTOR.equals(getJob()); + } + + public boolean isWriter() { + return WRITER.equals(getJob()); + } + + @Override + public String toString() { + return String.format("%s (%s)", name, isActor() ? character : job); + } + + public static final String WRITER = "Writer"; + public static final String DIRECTOR = "Director"; + public static final String ACTOR = "Actor"; + + public static final Comparator CREDIT_ORDER = comparing(Person::getOrder, nullsLast(naturalOrder())); + +} diff --git a/source/net/filebot/web/TMDbClient.java b/source/net/filebot/web/TMDbClient.java index db8bb022..73a422bc 100644 --- a/source/net/filebot/web/TMDbClient.java +++ b/source/net/filebot/web/TMDbClient.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -35,8 +36,6 @@ import net.filebot.Cache; import net.filebot.CacheType; import net.filebot.Language; import net.filebot.ResourceManager; -import net.filebot.web.TMDbClient.MovieInfo.MovieProperty; -import net.filebot.web.TMDbClient.Person.PersonProperty; public class TMDbClient implements MovieIdentificationService, ArtworkProvider { @@ -241,9 +240,19 @@ public class TMDbClient implements MovieIdentificationService, ArtworkProvider { List cast = new ArrayList(); try { + // { "cast_id":20, "character":"Gandalf", "credit_id":"52fe4a87c3a368484e158bb7", "id":1327, "name":"Ian McKellen", "order":1, "profile_path":"/c51mP46oPgAgFf7bFWVHlScZynM.jpg" } + Function normalize = s -> replaceSpace(s, " ").trim(); // user data may not be well-formed + Stream.of("cast", "crew").flatMap(section -> streamJsonObjects(getMap(response, "casts"), section)).map(it -> { - return getEnumMap(it, PersonProperty.class); - }).map(Person::new).forEach(cast::add); + String name = getStringValue(it, "name", normalize); + String character = getStringValue(it, "character", normalize); + String job = getStringValue(it, "job", normalize); + String department = getStringValue(it, "department", normalize); + Integer order = getInteger(it, "order"); + URL image = getStringValue(it, "profile_path", this::resolveImage); + + return new Person(name, character, job, department, order, image); + }).sorted(Person.CREDIT_ORDER).forEach(cast::add); } catch (Exception e) { debug.warning(format("Bad data: casts => %s", response)); } @@ -271,24 +280,35 @@ public class TMDbClient implements MovieIdentificationService, ArtworkProvider { @Override public List getArtwork(int id, String category, Locale locale) throws Exception { - Object config = request("configuration", emptyMap(), Locale.ROOT, REQUEST_LIMIT); - URL baseUrl = new URL(getString(getMap(config, "images"), "secure_base_url")); - Object images = request("movie/" + id + "/images", emptyMap(), Locale.ROOT, REQUEST_LIMIT); return streamJsonObjects(images, category).map(it -> { - try { - String path = "original" + getString(it, "file_path"); - String width = getString(it, "width"); - String height = getString(it, "height"); - Locale language = getStringValue(it, "iso_639_1", Locale::new); + URL image = getStringValue(it, "file_path", this::resolveImage); + String width = getString(it, "width"); + String height = getString(it, "height"); + Locale language = getStringValue(it, "iso_639_1", Locale::new); - return new Artwork(this, Stream.of(category, String.join("x", width, height)), new URL(baseUrl, path), language, null); - } catch (Exception e) { - debug.log(Level.WARNING, e, e::getMessage); - return null; - } - }).filter(Objects::nonNull).sorted(Artwork.RATING_ORDER).collect(toList()); + return new Artwork(Stream.of(category, String.join("x", width, height)), image, language, null); + }).sorted(Artwork.RATING_ORDER).collect(toList()); + } + + protected Object getConfiguration() throws Exception { + return request("configuration", emptyMap(), Locale.ROOT, REQUEST_LIMIT); + } + + protected URL resolveImage(String path) { + if (path == null || path.isEmpty()) { + return null; + } + + try { + String mirror = (String) Cache.getCache(getName(), CacheType.Monthly).computeIfAbsent("configuration.base_url", it -> { + return getString(getMap(getConfiguration(), "images"), "base_url"); + }); + return new URL(mirror + "original" + path); + } catch (Exception e) { + throw new IllegalArgumentException(path, e); + } } protected Object request(String resource, Map parameters, Locale locale, final FloodLimit limit) throws Exception { @@ -334,11 +354,11 @@ public class TMDbClient implements MovieIdentificationService, ArtworkProvider { throw new IllegalArgumentException("Illegal language code: " + language); } - public static class MovieInfo implements Serializable { + public static enum MovieProperty { + adult, backdrop_path, budget, homepage, id, imdb_id, original_title, overview, popularity, poster_path, release_date, revenue, runtime, tagline, title, vote_average, vote_count, certification, collection + } - public static enum MovieProperty { - adult, backdrop_path, budget, homepage, id, imdb_id, original_title, overview, popularity, poster_path, release_date, revenue, runtime, tagline, title, vote_average, vote_count, certification, collection - } + public static class MovieInfo implements Serializable { protected Map fields; @@ -573,77 +593,11 @@ public class TMDbClient implements MovieIdentificationService, ArtworkProvider { } } - public static class Person implements Serializable { + public static class Trailer implements Serializable { - public static enum PersonProperty { - name, character, job, department - } - - protected Map fields; - - protected Person() { - // used by serializer - } - - public Person(Map fields) { - this.fields = new EnumMap(fields); - } - - public Person(String name, String character, String job) { - fields = new EnumMap(PersonProperty.class); - fields.put(PersonProperty.name, name); - fields.put(PersonProperty.character, character); - fields.put(PersonProperty.job, job); - } - - public String get(Object key) { - return get(PersonProperty.valueOf(key.toString())); - } - - public String get(PersonProperty key) { - // replace null with empty string and normalize spaces - return replaceSpace(Objects.toString(fields.get(key), ""), " ").trim(); - } - - public String getName() { - return get(PersonProperty.name); - } - - public String getCharacter() { - return get(PersonProperty.character); - } - - public String getJob() { - return get(PersonProperty.job); - } - - public String getDepartment() { - return get(PersonProperty.department); - } - - public boolean isActor() { - return fields.containsKey(PersonProperty.character); - } - - public boolean isDirector() { - return "Director".equals(getJob()); - } - - public boolean isWriter() { - return "Writer".equals(getJob()); - } - - @Override - public String toString() { - return fields.toString(); - } - } - - public static class Trailer { - - private String type; - private String name; - private Map sources; + protected String type; + protected String name; + protected Map sources; public Trailer(String type, String name, Map sources) { this.type = type; diff --git a/source/net/filebot/web/TheTVDBClient.java b/source/net/filebot/web/TheTVDBClient.java index a23903a9..e73d5b79 100644 --- a/source/net/filebot/web/TheTVDBClient.java +++ b/source/net/filebot/web/TheTVDBClient.java @@ -22,7 +22,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; -import java.util.logging.Level; import java.util.stream.Stream; import javax.swing.Icon; @@ -151,7 +150,7 @@ public class TheTVDBClient extends AbstractEpisodeListProvider implements Artwor info.setOverview(getString(data, "overview")); info.setAirsDayOfWeek(getString(data, "airsDayOfWeek")); info.setAirsTime(getString(data, "airsTime")); - info.setBannerUrl(getStringValue(data, "banner", this::resolveBanner)); + info.setBannerUrl(getStringValue(data, "banner", this::resolveImage)); info.setLastUpdated(getStringValue(data, "lastUpdated", Long::new)); return info; @@ -242,21 +241,16 @@ public class TheTVDBClient extends AbstractEpisodeListProvider implements Artwor Object json = requestJson("series/" + id + "/images/query?keyType=" + category, locale, Cache.ONE_MONTH); return streamJsonObjects(json, "data").map(it -> { - try { - String subKey = getString(it, "subKey"); - String fileName = getString(it, "fileName"); - String resolution = getString(it, "resolution"); - Double rating = getDecimal(getMap(it, "ratingsInfo"), "average"); + String subKey = getString(it, "subKey"); + String resolution = getString(it, "resolution"); + URL url = getStringValue(it, "fileName", this::resolveImage); + Double rating = getDecimal(getMap(it, "ratingsInfo"), "average"); - return new Artwork(this, Stream.of(category, subKey, resolution), resolveBanner(fileName), locale, rating); - } catch (Exception e) { - debug.log(Level.WARNING, e, e::getMessage); - return null; - } - }).filter(Objects::nonNull).sorted(Artwork.RATING_ORDER).collect(toList()); + return new Artwork(Stream.of(category, subKey, resolution), url, locale, rating); + }).sorted(Artwork.RATING_ORDER).collect(toList()); } - protected URL resolveBanner(String path) { + protected URL resolveImage(String path) { if (path == null || path.isEmpty()) { return null; } @@ -265,7 +259,7 @@ public class TheTVDBClient extends AbstractEpisodeListProvider implements Artwor try { return new URL("http://thetvdb.com/banners/" + path); } catch (Exception e) { - throw new IllegalArgumentException(path); + throw new IllegalArgumentException(path, e); } } @@ -274,9 +268,18 @@ public class TheTVDBClient extends AbstractEpisodeListProvider implements Artwor return streamJsonObjects(response, "data").map(it -> getString(it, "abbreviation")).collect(toList()); } - public List> getActors(int id, Locale locale) throws Exception { + public List getActors(int id, Locale locale) throws Exception { Object response = requestJson("series/" + id + "/actors", locale, Cache.ONE_MONTH); - return streamJsonObjects(response, "data").map(it -> asMap(it)).collect(toList()); + + // e.g. [id:68414, seriesId:78874, name:Summer Glau, role:River Tam, sortOrder:2, image:actors/68414.jpg, imageAuthor:513, imageAdded:0000-00-00 00:00:00, lastUpdated:2011-08-18 11:53:14] + return streamJsonObjects(response, "data").map(it -> { + String name = getString(it, "name"); + String character = getString(it, "role"); + Integer order = getInteger(it, "sortOrder"); + URL image = getStringValue(it, "image", this::resolveImage); + + return new Person(name, character, null, null, order, image); + }).sorted(Person.CREDIT_ORDER).collect(toList()); } } diff --git a/test/net/filebot/web/TMDbClientTest.java b/test/net/filebot/web/TMDbClientTest.java index 007ead5b..0978f356 100644 --- a/test/net/filebot/web/TMDbClientTest.java +++ b/test/net/filebot/web/TMDbClientTest.java @@ -19,11 +19,11 @@ import net.filebot.web.TMDbClient.MovieInfo; public class TMDbClientTest { - TMDbClient tmdb = new TMDbClient("66308fb6e3fd850dde4c7d21df2e8306"); + static TMDbClient db = new TMDbClient("66308fb6e3fd850dde4c7d21df2e8306"); @Test public void searchByName() throws Exception { - List result = tmdb.searchMovie("Serenity", Locale.CHINESE); + List result = db.searchMovie("Serenity", Locale.CHINESE); Movie movie = result.get(0); assertEquals("冲出宁静号", movie.getName()); @@ -34,7 +34,7 @@ public class TMDbClientTest { @Test public void searchByNameWithYearShortName() throws Exception { - List result = tmdb.searchMovie("Up 2009", Locale.ENGLISH); + List result = db.searchMovie("Up 2009", Locale.ENGLISH); Movie movie = result.get(0); assertEquals("Up", movie.getName()); @@ -45,7 +45,7 @@ public class TMDbClientTest { @Test public void searchByNameWithYearNumberName() throws Exception { - List result = tmdb.searchMovie("9 (2009)", Locale.ENGLISH); + List result = db.searchMovie("9 (2009)", Locale.ENGLISH); Movie movie = result.get(0); assertEquals("9", movie.getName()); @@ -56,7 +56,7 @@ public class TMDbClientTest { @Test public void searchByNameGermanResults() throws Exception { - List result = tmdb.searchMovie("East of Eden", Locale.GERMAN); + List result = db.searchMovie("East of Eden", Locale.GERMAN); Movie movie = result.get(0); assertEquals("Jenseits von Eden", movie.getName()); @@ -66,7 +66,7 @@ public class TMDbClientTest { @Test public void searchByIMDB() throws Exception { - Movie movie = tmdb.getMovieDescriptor(new Movie(418279), Locale.ENGLISH); + Movie movie = db.getMovieDescriptor(new Movie(418279), Locale.ENGLISH); assertEquals("Transformers", movie.getName()); assertEquals(2007, movie.getYear(), 0); @@ -76,7 +76,7 @@ public class TMDbClientTest { @Test public void getMovieInfo() throws Exception { - MovieInfo movie = tmdb.getMovieInfo(new Movie(418279), Locale.ENGLISH, true); + MovieInfo movie = db.getMovieInfo(new Movie(418279), Locale.ENGLISH, true); assertEquals("Transformers", movie.getName()); assertEquals("2007-06-27", movie.getReleased().toString()); @@ -88,16 +88,27 @@ public class TMDbClientTest { @Test public void getArtwork() throws Exception { - Artwork a = tmdb.getArtwork(16320, "backdrops", Locale.ROOT).get(0); + Artwork a = db.getArtwork(16320, "backdrops", Locale.ROOT).get(0); assertEquals("[backdrops, 1920x1080]", a.getTags().toString()); assertEquals("https://image.tmdb.org/t/p/original/424MxHQe5Hfu92hTeRvZb5Giv0X.jpg", a.getUrl().toString()); } + @Test + public void getPeople() throws Exception { + Person p = db.getMovieInfo("16320", Locale.ENGLISH, true).getPeople().get(0); + assertEquals("Nathan Fillion", p.getName()); + assertEquals("Mal", p.getCharacter()); + assertEquals(null, p.getJob()); + assertEquals(null, p.getDepartment()); + assertEquals("0", p.getOrder().toString()); + assertEquals("http://image.tmdb.org/t/p/original/B7VTVtnKyFk0AtYjEbqzBQlPec.jpg", p.getImage().toString()); + } + @Ignore @Test public void floodLimit() throws Exception { for (Locale it : Locale.getAvailableLocales()) { - List results = tmdb.searchMovie("Serenity", it); + List results = db.searchMovie("Serenity", it); assertEquals(16320, results.get(0).getTmdbId()); } } diff --git a/test/net/filebot/web/TheTVDBClientTest.java b/test/net/filebot/web/TheTVDBClientTest.java index 901a3d66..19bc260b 100644 --- a/test/net/filebot/web/TheTVDBClientTest.java +++ b/test/net/filebot/web/TheTVDBClientTest.java @@ -9,7 +9,7 @@ import org.junit.Test; public class TheTVDBClientTest { - static TheTVDBClient thetvdb = new TheTVDBClient("BA864DEE427E384A"); + static TheTVDBClient db = new TheTVDBClient("BA864DEE427E384A"); SearchResult buffy = new SearchResult(70327, "Buffy the Vampire Slayer"); SearchResult wonderfalls = new SearchResult(78845, "Wonderfalls"); @@ -18,7 +18,7 @@ public class TheTVDBClientTest { @Test public void search() throws Exception { // test default language and query escaping (blanks) - List results = thetvdb.search("babylon 5", Locale.ENGLISH); + List results = db.search("babylon 5", Locale.ENGLISH); assertEquals(2, results.size()); @@ -30,7 +30,7 @@ public class TheTVDBClientTest { @Test public void searchGerman() throws Exception { - List results = thetvdb.search("Buffy the Vampire Slayer", Locale.GERMAN); + List results = db.search("Buffy the Vampire Slayer", Locale.GERMAN); assertEquals(2, results.size()); @@ -42,7 +42,7 @@ public class TheTVDBClientTest { @Test public void getEpisodeListAll() throws Exception { - List list = thetvdb.getEpisodeList(buffy, SortOrder.Airdate, Locale.ENGLISH); + List list = db.getEpisodeList(buffy, SortOrder.Airdate, Locale.ENGLISH); assertEquals(145, list.size()); @@ -69,7 +69,7 @@ public class TheTVDBClientTest { @Test public void getEpisodeListSingleSeason() throws Exception { - List list = thetvdb.getEpisodeList(wonderfalls, SortOrder.Airdate, Locale.ENGLISH); + List list = db.getEpisodeList(wonderfalls, SortOrder.Airdate, Locale.ENGLISH); Episode first = list.get(0); @@ -84,7 +84,7 @@ public class TheTVDBClientTest { @Test public void getEpisodeListNumbering() throws Exception { - List list = thetvdb.getEpisodeList(firefly, SortOrder.DVD, Locale.ENGLISH); + List list = db.getEpisodeList(firefly, SortOrder.DVD, Locale.ENGLISH); Episode first = list.get(0); assertEquals("Firefly", first.getSeriesName()); @@ -97,26 +97,26 @@ public class TheTVDBClientTest { } public void getEpisodeListLink() { - assertEquals("http://www.thetvdb.com/?tab=seasonall&id=78874", thetvdb.getEpisodeListLink(firefly).toString()); + assertEquals("http://www.thetvdb.com/?tab=seasonall&id=78874", db.getEpisodeListLink(firefly).toString()); } @Test public void lookupByID() throws Exception { - SearchResult series = thetvdb.lookupByID(78874, Locale.ENGLISH); + SearchResult series = db.lookupByID(78874, Locale.ENGLISH); assertEquals("Firefly", series.getName()); assertEquals(78874, series.getId()); } @Test public void lookupByIMDbID() throws Exception { - SearchResult series = thetvdb.lookupByIMDbID(303461, Locale.ENGLISH); + SearchResult series = db.lookupByIMDbID(303461, Locale.ENGLISH); assertEquals("Firefly", series.getName()); assertEquals(78874, series.getId()); } @Test public void getSeriesInfo() throws Exception { - TheTVDBSeriesInfo it = thetvdb.getSeriesInfo(80348, Locale.ENGLISH); + TheTVDBSeriesInfo it = db.getSeriesInfo(80348, Locale.ENGLISH); assertEquals(80348, it.getId(), 0); assertEquals("Action", it.getGenres().get(0)); @@ -134,7 +134,7 @@ public class TheTVDBClientTest { @Test public void getArtwork() throws Exception { - Artwork i = thetvdb.getArtwork(buffy.getId(), "fanart", Locale.ENGLISH).get(0); + Artwork i = db.getArtwork(buffy.getId(), "fanart", Locale.ENGLISH).get(0); assertEquals("[fanart, 1920x1080]", i.getTags().toString()); assertEquals("http://thetvdb.com/banners/fanart/original/70327-7.jpg", i.getUrl().toString()); @@ -145,8 +145,19 @@ public class TheTVDBClientTest { @Test public void getLanguages() throws Exception { - List languages = thetvdb.getLanguages(); + List languages = db.getLanguages(); assertEquals("[zh, en, sv, no, da, fi, nl, de, it, es, fr, pl, hu, el, tr, ru, he, ja, pt, cs, sl, hr, ko]", languages.toString()); } + @Test + public void getActors() throws Exception { + Person p = db.getActors(firefly.getId(), Locale.ENGLISH).get(0); + assertEquals("Alan Tudyk", p.getName()); + assertEquals("Hoban 'Wash' Washburne", p.getCharacter()); + assertEquals(null, p.getJob()); + assertEquals(null, p.getDepartment()); + assertEquals("0", p.getOrder().toString()); + assertEquals("http://thetvdb.com/banners/actors/68409.jpg", p.getImage().toString()); + } + }