From d2f4a7b1321d7984e2894949532bb3a52270c779 Mon Sep 17 00:00:00 2001 From: Omertron Date: Sat, 12 Jun 2010 10:46:58 +0000 Subject: [PATCH] Updated --- themoviedbapi/.classpath | 7 + themoviedbapi/.project | 17 + themoviedbapi/build.xml | 57 ++ .../moviejukebox/themoviedb/TheMovieDb.java | 608 ++++++++++++++++++ .../themoviedb/model/Artwork.java | 103 +++ .../themoviedb/model/Category.java | 50 ++ .../themoviedb/model/Country.java | 50 ++ .../themoviedb/model/MovieDB.java | 350 ++++++++++ .../moviejukebox/themoviedb/model/Person.java | 68 ++ .../themoviedb/tools/LogFormatter.java | 31 + .../themoviedb/tools/XMLHelper.java | 61 ++ themoviedbapi/src/readme.txt | 9 + 12 files changed, 1411 insertions(+) create mode 100644 themoviedbapi/.classpath create mode 100644 themoviedbapi/.project create mode 100644 themoviedbapi/build.xml create mode 100644 themoviedbapi/src/com/moviejukebox/themoviedb/TheMovieDb.java create mode 100644 themoviedbapi/src/com/moviejukebox/themoviedb/model/Artwork.java create mode 100644 themoviedbapi/src/com/moviejukebox/themoviedb/model/Category.java create mode 100644 themoviedbapi/src/com/moviejukebox/themoviedb/model/Country.java create mode 100644 themoviedbapi/src/com/moviejukebox/themoviedb/model/MovieDB.java create mode 100644 themoviedbapi/src/com/moviejukebox/themoviedb/model/Person.java create mode 100644 themoviedbapi/src/com/moviejukebox/themoviedb/tools/LogFormatter.java create mode 100644 themoviedbapi/src/com/moviejukebox/themoviedb/tools/XMLHelper.java create mode 100644 themoviedbapi/src/readme.txt diff --git a/themoviedbapi/.classpath b/themoviedbapi/.classpath new file mode 100644 index 000000000..b148297dc --- /dev/null +++ b/themoviedbapi/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/themoviedbapi/.project b/themoviedbapi/.project new file mode 100644 index 000000000..63e67b96e --- /dev/null +++ b/themoviedbapi/.project @@ -0,0 +1,17 @@ + + + themoviedbapi + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/themoviedbapi/build.xml b/themoviedbapi/build.xml new file mode 100644 index 000000000..ed4f360d9 --- /dev/null +++ b/themoviedbapi/build.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${project}${line.separator} + Build Date: ${builddate}${line.separator} + Revision: r${revision}${line.separator} + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themoviedbapi/src/com/moviejukebox/themoviedb/TheMovieDb.java b/themoviedbapi/src/com/moviejukebox/themoviedb/TheMovieDb.java new file mode 100644 index 000000000..9b1e8c7b6 --- /dev/null +++ b/themoviedbapi/src/com/moviejukebox/themoviedb/TheMovieDb.java @@ -0,0 +1,608 @@ +/* + * Copyright (c) 2004-2009 YAMJ Members + * http://code.google.com/p/moviejukebox/people/list + * + * Web: http://code.google.com/p/moviejukebox/ + * + * This software is licensed under a Creative Commons License + * See this page: http://code.google.com/p/moviejukebox/wiki/License + * + * For any reuse or distribution, you must make clear to others the + * license terms of this work. + */ + +package com.moviejukebox.themoviedb; + +import java.net.URLEncoder; +import java.util.Iterator; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import com.moviejukebox.themoviedb.model.*; +import com.moviejukebox.themoviedb.tools.*; + +/** + * This is the main class for the API to connect to TheMovieDb.org The implementation is for v2.1 of the API as detailed here + * http://api.themoviedb.org/2.1/docs/ + * + * @author Stuart.Boston + * @version 1.1 + */ +public class TheMovieDb { + + private String apiKey; + private static String apiSite = "http://api.themoviedb.org/2.1/"; + private static String defaultLanguage = "en"; + private static Logger logger; + + public TheMovieDb(String apiKey) { + logger = Logger.getLogger("TheMovieDB"); + LogFormatter mjbFormatter = new LogFormatter(); + ConsoleHandler ch = new ConsoleHandler(); + ch.setFormatter(mjbFormatter); + ch.setLevel(Level.FINE); + logger.addHandler(ch); + logger.setUseParentHandlers(true); + logger.setLevel(Level.ALL); + + this.apiKey = apiKey; + mjbFormatter.addApiKey(apiKey); + } + + /** + * Build the search URL from the search prefix and movie title. + * This will change between v2.0 and v2.1 of the API + * + * @param prefix The search prefix before the movie title + * @param language The two digit language code. E.g. en=English + * @param searchTerm The search key to use, e.g. movie title or IMDb ID + * @return The search URL + */ + private String buildSearchUrl(String prefix, String searchTerm, String language) { + String searchUrl = apiSite + prefix + "/" + language + "/xml/" + apiKey + "/" + searchTerm; + logger.finest("Search URL: " + searchUrl); + return searchUrl; + } + + /** + * Searches the database using the movie title passed + * + * @param movieTitle The title to search for + * @param language The two digit language code. E.g. en=English + * @return A movie bean with the data extracted + */ + public MovieDB moviedbSearch(String movieTitle, String language) { + XMLEventReader xmlReader = null; + MovieDB movie = null; + + language = validateLanguage(language); + + // If the title is null, then exit + if (movieTitle == null || movieTitle.equals("")) + return movie; + + try { + String searchUrl = buildSearchUrl("Movie.search", URLEncoder.encode(movieTitle, "UTF-8"), language); + xmlReader = XMLHelper.getEventReader(searchUrl); + movie = parseMovieInfo(xmlReader); + } catch (Exception error) { + System.err.println("ERROR: TheMovieDb API -> " + error.getMessage()); + } finally { + XMLHelper.closeEventReader(xmlReader); + } + return movie; + } + + /** + * Searches the database using the IMDd reference + * + * @param imdbID IMDb reference, must include the "tt" at the start + * @param language The two digit language code. E.g. en=English + * @return A movie bean with the data extracted + */ + public MovieDB moviedbImdbLookup(String imdbID, String language) { + XMLEventReader xmlReader = null; + MovieDB movie = null; + + language = validateLanguage(language); + + // If the imdbID is null, then exit + if (imdbID == null || imdbID.equals("")) + return movie; + + try { + String searchUrl = buildSearchUrl("Movie.imdbLookup", imdbID, language); + xmlReader = XMLHelper.getEventReader(searchUrl); + movie = parseMovieInfo(xmlReader); + } catch (Exception error) { + System.err.println("ERROR: TheMovieDb API -> " + error.getMessage()); + } finally { + XMLHelper.closeEventReader(xmlReader); + } + return movie; + } + + /** + * Passes a null MovieDB object to the full function + * + * @param tmdbID TheMovieDB ID of the movie to get the information for + * @param language The two digit language code. E.g. en=English + * @return A movie bean with all of the information + */ + public MovieDB moviedbGetInfo(String tmdbID, String language) { + MovieDB movie = null; + movie = moviedbGetInfo(tmdbID, movie, language); + return movie; + } + + /** + * Gets all the information for a given TheMovieDb ID + * + * @param movie + * An existing MovieDB object to populate with the data + * @param tmdbID + * The Movie Db ID for the movie to get information for + * @param language + * The two digit language code. E.g. en=English + * @return A movie bean with all of the information + */ + public MovieDB moviedbGetInfo(String tmdbID, MovieDB movie, String language) { + XMLEventReader xmlReader = null; + + // If the tmdbID is null, then exit + if (tmdbID == null || tmdbID.equals("") || tmdbID.equalsIgnoreCase("UNKNOWN")) + return movie; + + language = validateLanguage(language); + + try { + String searchUrl = buildSearchUrl("Movie.getImages", tmdbID, language); + xmlReader = XMLHelper.getEventReader(searchUrl); + movie = parseMovieInfo(xmlReader); + } catch (Exception error) { + System.err.println("ERROR: TheMovieDb API -> " + error.getMessage()); + } finally { + XMLHelper.closeEventReader(xmlReader); + } + return movie; + } + + public MovieDB moviedbGetImages(String searchTerm, String language) { + MovieDB movie = null; + movie = moviedbGetInfo(searchTerm, movie, language); + return movie; + } + + /** + * Get all the image information from TheMovieDb. + * @param searchTerm Can be either the IMDb ID or TMDb ID + * @param movie + * @param language + * @return + */ + public MovieDB moviedbGetImages(String searchTerm, MovieDB movie, String language) { + XMLEventReader xmlReader = null; + + // If the searchTerm is null, then exit + if (searchTerm == null || searchTerm.equals("") || searchTerm.equalsIgnoreCase("UNKNOWN")) + return movie; + + language = validateLanguage(language); + + try { + String searchUrl = buildSearchUrl("Movie.getImages", searchTerm, language); + xmlReader = XMLHelper.getEventReader(searchUrl); + movie = parseMovieInfo(xmlReader); + } catch (Exception error) { + System.err.println("ERROR: TheMovieDb API -> " + error.getMessage()); + } finally { + XMLHelper.closeEventReader(xmlReader); + } + + return movie; + } + + /** + * Search the XML passed and decode to a movieDB bean + * + * @param xmlReader + * The XML stream read from TheMovieDB.org + * @return a MovieDB bean with the data + * @throws XMLStreamException + */ + // TODO Waring if match is low (i.e. score != 1.0) + @SuppressWarnings("unchecked") + public MovieDB parseMovieInfo(XMLEventReader xmlReader) throws XMLStreamException { + MovieDB movie = null; + try { + while (xmlReader.hasNext()) { + XMLEvent event = xmlReader.nextEvent(); + + if (event.isStartElement()) { + StartElement startElement = event.asStartElement(); + + if (startElement.getName().getLocalPart().equalsIgnoreCase("movie")) { + movie = new MovieDB(); + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("popularity")) { + event = xmlReader.nextEvent(); + movie.setPopularity(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("name")) { + event = xmlReader.nextEvent(); + movie.setTitle(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("type")) { + event = xmlReader.nextEvent(); + movie.setType(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("id")) { + event = xmlReader.nextEvent(); + movie.setId(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("imdb_id")) { + event = xmlReader.nextEvent(); + movie.setImdb(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("url")) { + event = xmlReader.nextEvent(); + movie.setUrl(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("overview")) { + event = xmlReader.nextEvent(); + movie.setOverview(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("rating")) { + event = xmlReader.nextEvent(); + movie.setRating(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("released")) { + event = xmlReader.nextEvent(); + movie.setReleaseDate(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("runtime")) { + event = xmlReader.nextEvent(); + movie.setRuntime(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("budget")) { + event = xmlReader.nextEvent(); + movie.setBudget(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("revenue")) { + event = xmlReader.nextEvent(); + movie.setRevenue(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("homepage")) { + event = xmlReader.nextEvent(); + movie.setHomepage(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("trailer")) { + event = xmlReader.nextEvent(); + movie.setTrailer(event.asCharacters().getData()); + continue; + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("categories")) { + event = xmlReader.nextEvent(); + startElement = event.asStartElement(); + + while (!event.isEndElement() && !event.asEndElement().getName().getLocalPart().equalsIgnoreCase("category")) { + Category category = new Category(); + Iterator attributes = startElement.getAttributes(); + while (attributes.hasNext()) { + Attribute attribute = attributes.next(); + if (attribute.getName().toString().equals("type")) + category.setType(attribute.getValue()); + if (attribute.getName().toString().equals("url")) + category.setUrl(attribute.getValue()); + if (attribute.getName().toString().equals("name")) + category.setName(attribute.getValue()); + + } + movie.addCategory(category); + } + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("countries")) { + event = xmlReader.nextEvent(); + startElement = event.asStartElement(); + + while (!event.isEndElement() && !event.asEndElement().getName().getLocalPart().equalsIgnoreCase("country")) { + Country country = new Country(); + Iterator attributes = startElement.getAttributes(); + while (attributes.hasNext()) { + Attribute attribute = attributes.next(); + if (attribute.getName().toString().equals("code")) + country.setCode(attribute.getValue()); + if (attribute.getName().toString().equals("url")) + country.setUrl(attribute.getValue()); + if (attribute.getName().toString().equals("name")) + country.setName(attribute.getValue()); + } + movie.addProductionCountry(country); + } + } + } + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase("cast")) { + event = xmlReader.nextEvent(); + startElement = event.asStartElement(); + + while (!event.isEndElement() && !event.asEndElement().getName().getLocalPart().equalsIgnoreCase("person")) { + Person person = new Person(); + Iterator attributes = startElement.getAttributes(); + while (attributes.hasNext()) { + Attribute attribute = attributes.next(); + if (attribute.getName().toString().equals("url")) + person.setUrl(attribute.getValue()); + if (attribute.getName().toString().equals("name")) + person.setName(attribute.getValue()); + if (attribute.getName().toString().equals("job")) + person.setJob(attribute.getValue()); + if (attribute.getName().toString().equals("character")) + person.setCharacter(attribute.getValue()); + if (attribute.getName().toString().equals("id")) + person.setId(attribute.getValue()); + } + movie.addPerson(person); + } + } + } + + /* + * This processes the image elements. There are two formats to deal with: + * Movie.imdbLookup, Movie.getInfo & Movie.search: + * + * + * + * + * + * Movie.getImages: + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + if (checkStartEvent(event, "images")) { + event = xmlReader.nextEvent(); + + while (!checkEndEvent(event, "images")) { + if (checkStartEvent(event, "image")) { + Artwork artwork = new Artwork(); + Iterator attributes = event.asStartElement().getAttributes(); + while (attributes.hasNext()) { + Attribute attribute = attributes.next(); + if (attribute.getName().toString().equalsIgnoreCase("type")) + artwork.setType(attribute.getValue()); + if (attribute.getName().toString().equalsIgnoreCase("size")) + artwork.setSize(attribute.getValue()); + if (attribute.getName().toString().equalsIgnoreCase("url")) + artwork.setUrl(attribute.getValue()); + if (attribute.getName().toString().equalsIgnoreCase("id")) + artwork.setId(attribute.getValue()); + } + event = xmlReader.nextEvent(); // Skip the characters at the end of the attributes + movie.addArtwork(artwork); + } + + if (checkStartEvent(event, "poster")) { + Artwork artwork = new Artwork(); + String imageId = getImageId(event); + event = xmlReader.nextEvent(); // Skip the characters at the end of the attributes + event = xmlReader.nextEvent(); + + while (!checkEndEvent(event, "poster")) { + artwork = new Artwork(); + artwork.setType(Artwork.ARTWORK_TYPE_POSTER); + artwork.setId(imageId); + + if (checkStartEvent(event, "image")) { + Iterator attributes = event.asStartElement().getAttributes(); + while (attributes.hasNext()) { + Attribute attribute = attributes.next(); + if (attribute.getName().toString().equalsIgnoreCase("url")) + artwork.setUrl(attribute.getValue()); + if (attribute.getName().toString().equalsIgnoreCase("size")) + artwork.setSize(attribute.getValue()); + } + event = xmlReader.nextEvent(); // Skip the characters at the end of the attributes + movie.addArtwork(artwork); + } + event = xmlReader.nextEvent(); + } + } + + if (checkStartEvent(event, "backdrop")) { + Artwork artwork = new Artwork(); + String imageId = getImageId(event); + event = xmlReader.nextEvent(); // Skip the characters at the end of the attributes + event = xmlReader.nextEvent(); + + while (!checkEndEvent(event, "backdrop")) { + artwork = new Artwork(); + artwork.setType(Artwork.ARTWORK_TYPE_BACKDROP); + artwork.setId(imageId); + + if (checkStartEvent(event, "image")) { + Iterator attributes = event.asStartElement().getAttributes(); + while (attributes.hasNext()) { + Attribute attribute = attributes.next(); + if (attribute.getName().toString().equalsIgnoreCase("url")) + artwork.setUrl(attribute.getValue()); + if (attribute.getName().toString().equalsIgnoreCase("size")) + artwork.setSize(attribute.getValue()); + } + event = xmlReader.nextEvent(); // Skip the characters at the end of the attributes + movie.addArtwork(artwork); + } + event = xmlReader.nextEvent(); + } + } + event = xmlReader.nextEvent(); + } // While "images" + } // If "images" + } // if start element + + if (event.isEndElement()) { + EndElement endElement = event.asEndElement(); + if (endElement.getName().getLocalPart().equalsIgnoreCase("movie")) { + break; + } + } + } + } catch (Exception error) { + System.err.println("Error: " + error.getMessage()); + error.printStackTrace(); + } + return movie; + } + + /** + * Check to see if the event passed is a start element and matches the eventName + * @param event + * @param endString + * @return True if the event is an end element and matches the eventName + */ + private boolean checkStartEvent(XMLEvent event, String eventName) { + boolean validElement = false; + + if (event.isStartElement()) { + if (event.asStartElement().getName().getLocalPart().equalsIgnoreCase(eventName)) { + validElement = true; + } + } + return validElement; + } + + /** + * Check to see if the event passed is an end element and matches the eventName + * @param event + * @param endString + * @return True if the event is an end element and matches the eventName + */ + private boolean checkEndEvent(XMLEvent event, String eventName) { + boolean validElement = false; + + if (event.isEndElement()) { + if (event.asEndElement().getName().getLocalPart().equalsIgnoreCase(eventName)) { + validElement = true; + } + } + return validElement; + } + + /** + * Find the ID in the element attributes + * @param event + * @return the imageId + */ + @SuppressWarnings({"unchecked"}) + private String getImageId(XMLEvent event) { + String imageId = null; + + try { + // read the id attribute from the element + Iterator attributes = event.asStartElement().getAttributes(); + while (attributes.hasNext()) { + Attribute attribute = attributes.next(); + if (attribute.getName().toString().equalsIgnoreCase("id")) + imageId = attribute.getValue(); + } + } catch (Exception error) { + imageId = null; + } + + return imageId; + } + + /** + * This function will check the passed language against a list of known themoviedb.org languages + * Currently the only available language is English "en" and so that is what this function returns + * @param language + * @return + */ + private String validateLanguage(String language) { + if (language == null) { + language = defaultLanguage; + } else { + language = defaultLanguage; + } + return language; + } +} diff --git a/themoviedbapi/src/com/moviejukebox/themoviedb/model/Artwork.java b/themoviedbapi/src/com/moviejukebox/themoviedb/model/Artwork.java new file mode 100644 index 000000000..6f2de7579 --- /dev/null +++ b/themoviedbapi/src/com/moviejukebox/themoviedb/model/Artwork.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2004-2009 YAMJ Members + * http://code.google.com/p/moviejukebox/people/list + * + * Web: http://code.google.com/p/moviejukebox/ + * + * This software is licensed under a Creative Commons License + * See this page: http://code.google.com/p/moviejukebox/wiki/License + * + * For any reuse or distribution, you must make clear to others the + * license terms of this work. + */ + +package com.moviejukebox.themoviedb.model; + +/** + * This is the new bean for the Artwork + * + * @author Stuart.Boston + * + */ +public class Artwork implements Comparable { + public static String ARTWORK_TYPE_POSTER = "poster"; + public static String ARTWORK_TYPE_BACKDROP = "backdrop"; + public static String[] ARTWORK_TYPES = {ARTWORK_TYPE_POSTER, ARTWORK_TYPE_BACKDROP}; + + public static String ARTWORK_SIZE_ORIGINAL = "original"; + public static String ARTWORK_SIZE_THUMB = "thumb"; + public static String ARTWORK_SIZE_MID = "mid"; + public static String ARTWORK_SIZE_COVER = "cover"; + public static String ARTWORK_SIZE_POSTER = "poster"; + public static String[] ARTWORK_SIZES = {ARTWORK_SIZE_ORIGINAL, ARTWORK_SIZE_THUMB, ARTWORK_SIZE_MID, ARTWORK_SIZE_COVER, ARTWORK_SIZE_POSTER}; + + public String type; + public String size; + public String url; + public int id; + + public String[] getArtworkSizes() { + return ARTWORK_SIZES; + } + + public String[] getArtworkTypes() { + return ARTWORK_TYPES; + } + + public String getType() { + if (type == null) { + return MovieDB.UNKNOWN; + } else { + return type; + } + } + + public void setType(String type) { + this.type = type; + } + + public String getSize() { + if (size == null) { + return MovieDB.UNKNOWN; + } else { + return size; + } + } + + public void setSize(String size) { + this.size = size; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public int getId() { + return id; + } + + public void setId(String id) { + try { + this.id = Integer.parseInt(id); + } catch (Exception ignore) { + // If there is an issue with casting the Id then use Zero + this.id = 0; + } + } + + public void setId(int id) { + this.id = id; + } + + @Override + public int compareTo(Object otherArtwork) throws ClassCastException { + if (!(otherArtwork instanceof Artwork)) + throw new ClassCastException("TheMovieDB API: An Artwork object is expected."); + int anotherId = ((Artwork) otherArtwork).getId(); + return this.id - anotherId; + } + } diff --git a/themoviedbapi/src/com/moviejukebox/themoviedb/model/Category.java b/themoviedbapi/src/com/moviejukebox/themoviedb/model/Category.java new file mode 100644 index 000000000..b9bff0a32 --- /dev/null +++ b/themoviedbapi/src/com/moviejukebox/themoviedb/model/Category.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004-2009 YAMJ Members + * http://code.google.com/p/moviejukebox/people/list + * + * Web: http://code.google.com/p/moviejukebox/ + * + * This software is licensed under a Creative Commons License + * See this page: http://code.google.com/p/moviejukebox/wiki/License + * + * For any reuse or distribution, you must make clear to others the + * license terms of this work. + */ + +package com.moviejukebox.themoviedb.model; + +/** + * Category from the MovieDB.org + * + * @author Stuart.Boston + * + */ +public class Category { + public String type; + public String name; + public String url; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/themoviedbapi/src/com/moviejukebox/themoviedb/model/Country.java b/themoviedbapi/src/com/moviejukebox/themoviedb/model/Country.java new file mode 100644 index 000000000..db08d6992 --- /dev/null +++ b/themoviedbapi/src/com/moviejukebox/themoviedb/model/Country.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004-2009 YAMJ Members + * http://code.google.com/p/moviejukebox/people/list + * + * Web: http://code.google.com/p/moviejukebox/ + * + * This software is licensed under a Creative Commons License + * See this page: http://code.google.com/p/moviejukebox/wiki/License + * + * For any reuse or distribution, you must make clear to others the + * license terms of this work. + */ + +package com.moviejukebox.themoviedb.model; + +/** + * Country from the MovieDB.org + * + * @author Stuart.Boston + * + */ +public class Country { + public String url; + public String name; + public String code; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } +} diff --git a/themoviedbapi/src/com/moviejukebox/themoviedb/model/MovieDB.java b/themoviedbapi/src/com/moviejukebox/themoviedb/model/MovieDB.java new file mode 100644 index 000000000..0c84bce36 --- /dev/null +++ b/themoviedbapi/src/com/moviejukebox/themoviedb/model/MovieDB.java @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2004-2009 YAMJ Members + * http://code.google.com/p/moviejukebox/people/list + * + * Web: http://code.google.com/p/moviejukebox/ + * + * This software is licensed under a Creative Commons License + * See this page: http://code.google.com/p/moviejukebox/wiki/License + * + * For any reuse or distribution, you must make clear to others the + * license terms of this work. + */ + +package com.moviejukebox.themoviedb.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * This is the Movie Search bean for the MovieDb.org search + * + * @author Stuart.Boston + */ + +public class MovieDB { + public static String UNKNOWN = "UNKNOWN"; + + private String score = UNKNOWN; + private String popularity = UNKNOWN; + private String title = UNKNOWN; + private String type = UNKNOWN; + private String id = UNKNOWN; + private String imdb = UNKNOWN; + private String url = UNKNOWN; + private String overview = UNKNOWN; + private String rating = UNKNOWN; + private String releaseDate = UNKNOWN; + private String runtime = UNKNOWN; + private String budget = UNKNOWN; + private String revenue = UNKNOWN; + private String homepage = UNKNOWN; + private String trailer = UNKNOWN; + private List artwork = new ArrayList(); + private List countries = new ArrayList(); + private List people = new ArrayList(); + private List categories = new ArrayList(); + + public String getScore() { + return score; + } + + public void setScore(String score) { + this.score = score; + } + + public String getPopularity() { + return popularity; + } + + public void setPopularity(String popularity) { + this.popularity = popularity; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getImdb() { + return imdb; + } + + public void setImdb(String imdb) { + this.imdb = imdb; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getOverview() { + return overview; + } + + public void setOverview(String overview) { + this.overview = overview; + } + + public String getReleaseDate() { + return releaseDate; + } + + public void setReleaseDate(String releaseDate) { + this.releaseDate = releaseDate; + } + + public String getRating() { + return rating; + } + + public void setRating(String rating) { + this.rating = rating; + } + + public String getRuntime() { + return runtime; + } + + public void setRuntime(String runtime) { + this.runtime = runtime; + } + + public String getBudget() { + return budget; + } + + public void setBudget(String budget) { + this.budget = budget; + } + + public String getRevenue() { + return revenue; + } + + public void setRevenue(String revenue) { + this.revenue = revenue; + } + + public String getHomepage() { + return homepage; + } + + public void setHomepage(String homepage) { + this.homepage = homepage; + } + + public String getTrailer() { + return trailer; + } + + public void setTrailer(String trailer) { + this.trailer = trailer; + } + + /** + * Add a piece of artwork to the artwork array + * @param artworkType must be one of Artwork.ARTWORK_TYPES + * @param artworkSize must be one of Artwork.ARTWORK_SIZES + * @param artworkUrl + * @param posterId + */ + public void addArtwork(String artworkType, String artworkSize, String artworkUrl, String artworkId) { + if (validateElement(Artwork.ARTWORK_TYPES, artworkType) && validateElement(Artwork.ARTWORK_SIZES, artworkSize)) { + Artwork newArtwork = new Artwork(); + + newArtwork.setType(artworkType); + newArtwork.setSize(artworkSize); + newArtwork.setUrl(artworkUrl); + newArtwork.setId(artworkId); + + artwork.add(newArtwork); + Collections.sort(artwork); + } + return; + } + + /** + * Add a piece of artwork to the artwork array + * @param newArtwork an Artwork object to add to the array + */ + public void addArtwork(Artwork newArtwork) { + if (validateElement(Artwork.ARTWORK_TYPES, newArtwork.getType()) && validateElement(Artwork.ARTWORK_SIZES, newArtwork.getSize())) { + artwork.add(newArtwork); + Collections.sort(artwork); + } + return; + } + + /** + * Check to see if element is contained in elementArray + * @param elementArray + * @param element + * @return + */ + private boolean validateElement(String[] elementArray, String element) { + boolean valid = false; + + for (String arrayEntry : elementArray) { + if (arrayEntry.equalsIgnoreCase(element)) { + valid = true; + break; + } + } + + return valid; + } + + public List getProductionCountries() { + return countries; + } + + public void addProductionCountry(Country country) { + if (country != null) { + countries.add(country); + } + } + + public List getPeople() { + return people; + } + + public void addPerson(Person person) { + if (person != null) { + people.add(person); + } + } + + public List getCategories() { + return categories; + } + + public void addCategory(Category category) { + if (category != null) { + categories.add(category); + } + } + + /** + * Return all the artwork for a movie + * @return + */ + public List getArtwork() { + return artwork; + } + + /** + * Get all the artwork of a specific type + * @param artworkType + * @return + */ + public List getArtwork(String artworkType) { + // Validate the Type and Size arguments + if (!validateElement(Artwork.ARTWORK_TYPES, artworkType)) { + return null; + } + + List artworkList = new ArrayList(); + + for (Artwork singleArtwork : artwork) { + if (singleArtwork.getType().equalsIgnoreCase(artworkType)) { + artworkList.add(singleArtwork); + } + } + + return artworkList; + } + + /** + * Get all artwork of a specific Type and Size + * @param artworkType + * @param artworkSize + * @return + */ + public List getArtwork(String artworkType, String artworkSize) { + List artworkList = new ArrayList(); + // Validate the Type and Size arguments + if (!validateElement(Artwork.ARTWORK_TYPES, artworkType) && !validateElement(Artwork.ARTWORK_SIZES, artworkSize)) { + return null; + } + + for (Artwork singleArtwork : artwork) { + if (singleArtwork.getType().equalsIgnoreCase(artworkType) && singleArtwork.getSize().equalsIgnoreCase(artworkSize)) { + artworkList.add(singleArtwork); + } + } + + return artworkList; + } + + /** + * Return a specific artwork entry for a Type & Size + * @param artworkType + * @param artworkSize + * @param artworkNumber + * @return + */ + public Artwork getArtwork(String artworkType, String artworkSize, int artworkNumber) { + // Validate the Type and Size arguments + if (!validateElement(Artwork.ARTWORK_TYPES, artworkType) && !validateElement(Artwork.ARTWORK_SIZES, artworkSize)) { + return null; + } + + // Validate the number + if (artworkNumber <= 0) { + artworkNumber = 0; + } else { + // Artwork elements start at 0 (Zero) + artworkNumber -= 1; + } + + List artworkList = getArtwork(artworkType, artworkSize); + + int artworkCount = artworkList.size(); + if (artworkCount < 1) { + return null; + } + + // If the number requested is greater than the array size, loop around until it's within scope + while (artworkNumber > artworkCount) { + artworkNumber = artworkNumber - artworkCount; + } + + return artworkList.get(artworkNumber); + } + + /** + * Get the first artwork that matches the Type and Size + * @param artworkType + * @param artworkSize + * @return + */ + public Artwork getFirstArtwork(String artworkType, String artworkSize) { + return getArtwork(artworkType, artworkSize, 1); + } + +} diff --git a/themoviedbapi/src/com/moviejukebox/themoviedb/model/Person.java b/themoviedbapi/src/com/moviejukebox/themoviedb/model/Person.java new file mode 100644 index 000000000..b76ea3788 --- /dev/null +++ b/themoviedbapi/src/com/moviejukebox/themoviedb/model/Person.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2004-2009 YAMJ Members + * http://code.google.com/p/moviejukebox/people/list + * + * Web: http://code.google.com/p/moviejukebox/ + * + * This software is licensed under a Creative Commons License + * See this page: http://code.google.com/p/moviejukebox/wiki/License + * + * For any reuse or distribution, you must make clear to others the + * license terms of this work. + */ + +package com.moviejukebox.themoviedb.model; + +/** + * This is the new bean for the Person + * + * @author Stuart.Boston + * + */ +public class Person { + public String url; + public String name; + public String job; + public String character; + public String id; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getJob() { + return job; + } + + public void setJob(String job) { + this.job = job; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getCharacter() { + return character; + } + + public void setCharacter(String character) { + this.character = character; + } +} diff --git a/themoviedbapi/src/com/moviejukebox/themoviedb/tools/LogFormatter.java b/themoviedbapi/src/com/moviejukebox/themoviedb/tools/LogFormatter.java new file mode 100644 index 000000000..42d5e3bef --- /dev/null +++ b/themoviedbapi/src/com/moviejukebox/themoviedb/tools/LogFormatter.java @@ -0,0 +1,31 @@ +package com.moviejukebox.themoviedb.tools; + +import java.security.PrivilegedAction; +import java.util.logging.LogRecord; + +public class LogFormatter extends java.util.logging.Formatter +{ + private static String API_KEY = null; + private static String EOL = (String)java.security.AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return System.getProperty("line.separator"); + } + }); + + public synchronized String format(LogRecord logRecord) { + String logMessage = logRecord.getMessage(); + + logMessage = "[TheMovieDb API] " + logMessage.replace(API_KEY, "[APIKEY]") + EOL; + + Throwable thrown = logRecord.getThrown(); + if (thrown != null) { + logMessage = logMessage + thrown.toString(); + } + return logMessage; + } + + public void addApiKey(String apiKey) { + API_KEY = apiKey; + return; + } +} diff --git a/themoviedbapi/src/com/moviejukebox/themoviedb/tools/XMLHelper.java b/themoviedbapi/src/com/moviejukebox/themoviedb/tools/XMLHelper.java new file mode 100644 index 000000000..8b8e55969 --- /dev/null +++ b/themoviedbapi/src/com/moviejukebox/themoviedb/tools/XMLHelper.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004-2009 YAMJ Members + * http://code.google.com/p/moviejukebox/people/list + * + * Web: http://code.google.com/p/moviejukebox/ + * + * This software is licensed under a Creative Commons License + * See this page: http://code.google.com/p/moviejukebox/wiki/License + * + * For any reuse or distribution, you must make clear to others the + * license terms of this work. + */ + +package com.moviejukebox.themoviedb.tools; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; + +/** + * + * @author altman.matthew (Original) + * @author stuart.boston + */ +public class XMLHelper { + + public static XMLEventReader getEventReader(String url) throws IOException, XMLStreamException { + InputStream in = (new URL(url)).openStream(); + return XMLInputFactory.newInstance().createXMLEventReader(in); + } + + public static void closeEventReader(XMLEventReader reader) { + if (reader != null) { + try { + reader.close(); + } catch (XMLStreamException ex) { + System.err.println("ERROR: TheMovieDb API -> " + ex.getMessage()); + } + } + } + + public static String getCData(XMLEventReader r) throws XMLStreamException { + StringBuffer sb = new StringBuffer(); + while (r.peek().isCharacters()) { + sb.append(r.nextEvent().asCharacters().getData()); + } + return sb.toString().trim(); + } + + public static int parseInt(XMLEventReader r) throws XMLStreamException { + int i = 0; + String val = getCData(r); + if (val != null && !val.isEmpty()) { + i = Integer.parseInt(val); + } + return i; + } +} diff --git a/themoviedbapi/src/readme.txt b/themoviedbapi/src/readme.txt new file mode 100644 index 000000000..f481fb77c --- /dev/null +++ b/themoviedbapi/src/readme.txt @@ -0,0 +1,9 @@ +Author: Stuart.Boston AT Gmail DOT com (Omertron) + +Originally written for use by YetAnotherMovieJukebox (YAMJ) http://code.google.com/p/moviejukebox/ +But anyone can feel free to use it for other projects as well. + +This uses TheMovieDB.org API as specified here http://api.themoviedb.org/ +TheMovieDB.org is an excellent open database for movie and film content. I encourage you to check it +out and contribute to keep it growing. +http://www.themoviedb.org \ No newline at end of file