package com.flickr4java.flickr.stats;
import com.flickr4java.flickr.FlickrException;
import com.flickr4java.flickr.FlickrRuntimeException;
import com.flickr4java.flickr.Response;
import com.flickr4java.flickr.Transport;
import com.flickr4java.flickr.photos.Photo;
import com.flickr4java.flickr.photos.PhotoList;
import com.flickr4java.flickr.photos.PhotoUtils;
import com.flickr4java.flickr.util.XMLUtilities;
import org.apache.log4j.Logger;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Interface to the Stats API.
*
* @author Darren Greaves
* @version $Id$ Copyright (c) 2012 Darren Greaves.
*/
public class StatsInterface {
/**
* Logger for log4j.
*/
@SuppressWarnings("unused")
private static Logger _log = Logger.getLogger(StatsInterface.class);
private static final String METHOD_GET_COLLECTION_DOMAINS = "flickr.stats.getCollectionDomains";
private static final String METHOD_GET_COLLECTION_REFERRERS = "flickr.stats.getCollectionReferrers";
private static final String METHOD_GET_COLLECTION_STATS = "flickr.stats.getCollectionStats";
private static final String METHOD_GET_CSV_FILES = "flickr.stats.getCSVFiles";
private static final String METHOD_GET_PHOTO_DOMAINS = "flickr.stats.getPhotoDomains";
private static final String METHOD_GET_PHOTO_REFERRERS = "flickr.stats.getPhotoReferrers";
private static final String METHOD_GET_PHOTO_STATS = "flickr.stats.getPhotoStats";
private static final String METHOD_GET_PHOTOSET_DOMAINS = "flickr.stats.getPhotosetDomains";
private static final String METHOD_GET_PHOTOSET_REFERRERS = "flickr.stats.getPhotosetReferrers";
private static final String METHOD_GET_PHOTOSET_STATS = "flickr.stats.getPhotosetStats";
private static final String METHOD_GET_PHOTOSTREAM_DOMAINS = "flickr.stats.getPhotostreamDomains";
private static final String METHOD_GET_PHOTOSTREAM_REFERRERS = "flickr.stats.getPhotostreamReferrers";
private static final String METHOD_GET_PHOTOSTREAM_STATS = "flickr.stats.getPhotostreamStats";
private static final String METHOD_GET_POPULAR_PHOTOS = "flickr.stats.getPopularPhotos";
private static final String METHOD_GET_TOTAL_VIEWS = "flickr.stats.getTotalViews";
private final String apiKey;
private final String sharedSecret;
private final Transport transportAPI;
public StatsInterface(String apiKey, String sharedSecret, Transport transportAPI) {
this.apiKey = apiKey;
this.sharedSecret = sharedSecret;
this.transportAPI = transportAPI;
}
/**
* Get a list of referring domains for a collection.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param collectionId
* (Optional) The id of the collection to get stats for. If not provided, stats for all collections will be returned.
* @param perPage
* (Optional) Number of domains to return per page. If this argument is omitted, it defaults to 25. The maximum allowed value is 100.
* @param page
* (Optional) The page of results to return. If this argument is omitted, it defaults to 1.
* @see "http://www.flickr.com/services/api/flickr.stats.getCollectionDomains.html"
*/
public DomainList getCollectionDomains(Date date, String collectionId, int perPage, int page) throws FlickrException {
return getDomains(METHOD_GET_COLLECTION_DOMAINS, "collection_id", collectionId, date, perPage, page);
}
/**
* Get a list of referrers from a given domain to a collection.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param domain
* (Required) The domain to return referrers for. This should be a hostname (eg: "flickr.com") with no protocol or pathname.
* @param collectionId
* (Optional) The id of the collection to get stats for. If not provided, stats for all collections will be returned.
* @param perPage
* (Optional) Number of domains to return per page. If this argument is omitted, it defaults to 25. The maximum allowed value is 100.
* @param page
* (Optional) The page of results to return. If this argument is omitted, it defaults to 1.
* @see "http://www.flickr.com/services/api/flickr.stats.getCollectionReferrers.html"
*/
public ReferrerList getCollectionReferrers(Date date, String domain, String collectionId, int perPage, int page) throws FlickrException {
return getReferrers(METHOD_GET_COLLECTION_REFERRERS, domain, "collection_id", collectionId, date, perPage, page);
}
/**
* Get the number of views, comments and favorites on a collection for a given date.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param collectionId
* (Required) The id (from the URL!) of the collection to get stats for.
* @see "http://www.flickr.com/services/api/flickr.stats.getCollectionStats.htm"
*/
public Stats getCollectionStats(String collectionId, Date date) throws FlickrException {
return getStats(METHOD_GET_COLLECTION_STATS, "collection_id", collectionId, date);
}
/**
* Returns a list of URLs for text files containing all your stats data (from November 26th 2007 onwards) for the currently auth'd user.
*
* @throws FlickrException
*
* @see "http://www.flickr.com/services/api/flickr.stats.getCSVFiles.html"
*/
public List<Csv> getCSVFiles() throws FlickrException {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("method", METHOD_GET_CSV_FILES);
Response response = transportAPI.get(transportAPI.getPath(), parameters, apiKey, sharedSecret);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
List<Csv> csvFiles = parseCsvFiles(response);
return csvFiles;
}
/**
* Get a list of referring domains for a photo.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param photoId
* (Optional) The id of the photo to get stats for. If not provided, stats for all photos will be returned.
* @param perPage
* (Optional) Number of domains to return per page. If this argument is omitted, it defaults to 25. The maximum allowed value is 100.
* @param page
* (Optional) The page of results to return. If this argument is omitted, it defaults to 1.
* @see "http://www.flickr.com/services/api/flickr.stats.getPhotoDomains.html"
*/
public DomainList getPhotoDomains(Date date, String photoId, int perPage, int page) throws FlickrException {
return getDomains(METHOD_GET_PHOTO_DOMAINS, "photo_id", photoId, date, perPage, page);
}
/**
* Get a list of referrers from a given domain to a photo.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param domain
* (Required) The domain to return referrers for. This should be a hostname (eg: "flickr.com") with no protocol or pathname.
* @param photoId
* (Optional) The id of the photo to get stats for. If not provided, stats for all photos will be returned.
* @param perPage
* (Optional) Number of domains to return per page. If this argument is omitted, it defaults to 25. The maximum allowed value is 100.
* @param page
* (Optional) The page of results to return. If this argument is omitted, it defaults to 1.
* @see "http://www.flickr.com/services/api/flickr.stats.getPhotoReferrers.html"
*/
public ReferrerList getPhotoReferrers(Date date, String domain, String photoId, int perPage, int page) throws FlickrException {
return getReferrers(METHOD_GET_PHOTO_REFERRERS, domain, "photo_id", photoId, date, perPage, page);
}
/**
* Get the number of views, comments and favorites on a photo for a given date.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param photoId
* (Required) The id of the photo to get stats for.
* @see "http://www.flickr.com/services/api/flickr.stats.getPhotoStats.htm"
*/
public Stats getPhotoStats(String photoId, Date date) throws FlickrException {
return getStats(METHOD_GET_PHOTO_STATS, "photo_id", photoId, date);
}
/**
* Get a list of referring domains for a photoset.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param photosetId
* (Optional) The id of the photoset to get stats for. If not provided, stats for all photos will be returned.
* @param perPage
* (Optional) Number of domains to return per page. If this argument is omitted, it defaults to 25. The maximum allowed value is 100.
* @param page
* (Optional) The page of results to return. If this argument is omitted, it defaults to 1.
* @see "http://www.flickr.com/services/api/flickr.stats.getPhotosetDomains.html"
*/
public DomainList getPhotosetDomains(Date date, String photosetId, int perPage, int page) throws FlickrException {
return getDomains(METHOD_GET_PHOTOSET_DOMAINS, "photoset_id", photosetId, date, perPage, page);
}
/**
* Get a list of referrers from a given domain to a photoset.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param domain
* (Required) The domain to return referrers for. This should be a hostname (eg: "flickr.com") with no protocol or pathname.
* @param photosetId
* (Optional) The id of the photoset to get stats for. If not provided, stats for all sets will be returned.
* @param perPage
* (Optional) Number of domains to return per page. If this argument is omitted, it defaults to 25. The maximum allowed value is 100.
* @param page
* (Optional) The page of results to return. If this argument is omitted, it defaults to 1.
* @see "http://www.flickr.com/services/api/flickr.stats.getPhotosetReferrers.html"
*/
public ReferrerList getPhotosetReferrers(Date date, String domain, String photosetId, int perPage, int page) throws FlickrException {
return getReferrers(METHOD_GET_PHOTOSET_REFERRERS, domain, "photoset_id", photosetId, date, perPage, page);
}
/**
* Get the number of views, comments and favorites on a photoset for a given date.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param photosetId
* (Required) The id of the photoset to get stats for.
* @see "http://www.flickr.com/services/api/flickr.stats.getPhotosetStats.htm"
*/
public Stats getPhotosetStats(String photosetId, Date date) throws FlickrException {
return getStats(METHOD_GET_PHOTOSET_STATS, "photoset_id", photosetId, date);
}
/**
* Get a list of referring domains for a photostream.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param perPage
* (Optional) Number of domains to return per page. If this argument is omitted, it defaults to 25. The maximum allowed value is 100.
* @param page
* (Optional) The page of results to return. If this argument is omitted, it defaults to 1.
* @see "http://www.flickr.com/services/api/flickr.stats.getPhotostreamDomains.html"
*/
public DomainList getPhotostreamDomains(Date date, int perPage, int page) throws FlickrException {
return getDomains(METHOD_GET_PHOTOSTREAM_DOMAINS, null, null, date, perPage, page);
}
/**
* Get a list of referrers from a given domain to a user's photostream.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @param domain
* (Required) The domain to return referrers for. This should be a hostname (eg: "flickr.com") with no protocol or pathname.
* @param perPage
* (Optional) Number of domains to return per page. If this argument is omitted, it defaults to 25. The maximum allowed value is 100.
* @param page
* (Optional) The page of results to return. If this argument is omitted, it defaults to 1.
* @see "http://www.flickr.com/services/api/flickr.stats.getPhotostreamReferrers.html"
*/
public ReferrerList getPhotostreamReferrers(Date date, String domain, int perPage, int page) throws FlickrException {
return getReferrers(METHOD_GET_PHOTOSTREAM_REFERRERS, domain, null, null, date, perPage, page);
}
/**
* Get the number of views, comments and favorites on a photostream for a given date.
*
* @param date
* (Required) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day.
* @see "http://www.flickr.com/services/api/flickr.stats.getPhotostreamStats.htm"
*/
public Stats getPhotostreamStats(Date date) throws FlickrException {
return getStats(METHOD_GET_PHOTOSTREAM_STATS, null, null, date);
}
/**
* List the photos with the most views, comments or favorites.
*
* @param date
* (Optional) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day. If no date is provided, all time view counts will be returned.
* @param sort
* (Optional) The order in which to sort returned photos. Defaults to views. The possible values are views, comments and favorites. Other sort
* options are available through flickr.photos.search.
* @param perPage
* (Optional) Number of referrers to return per page. If this argument is omitted, it defaults to 25. The maximum allowed value is 100.
* @param page
* (Optional) The page of results to return. If this argument is omitted, it defaults to 1.
* @throws FlickrException
* @see "http://www.flickr.com/services/api/flickr.stats.getPopularPhotos.html"
*/
public PhotoList<Photo> getPopularPhotos(Date date, StatsSort sort, int perPage, int page) throws FlickrException {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("method", METHOD_GET_POPULAR_PHOTOS);
if (date != null) {
parameters.put("date", String.valueOf(date.getTime() / 1000L));
}
if (sort != null) {
parameters.put("sort", sort.name());
}
addPaginationParameters(parameters, perPage, page);
Response response = transportAPI.get(transportAPI.getPath(), parameters, apiKey, sharedSecret);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
return parsePopularPhotos(response);
}
/**
* Get the overall view counts for an account
*
* @param date
* (Optional) Stats will be returned for this date. A day according to Flickr Stats starts at midnight GMT for all users, and timestamps will
* automatically be rounded down to the start of the day. If no date is provided, all time view counts will be returned.
* @throws FlickrException
*
* @see "http://www.flickr.com/services/api/flickr.stats.getTotalViews.html"
*/
public Totals getTotalViews(Date date) throws FlickrException {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("method", METHOD_GET_TOTAL_VIEWS);
if (date != null) {
parameters.put("date", String.valueOf(date.getTime() / 1000L));
}
Response response = transportAPI.get(transportAPI.getPath(), parameters, apiKey, sharedSecret);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
Totals totals = parseTotals(response);
return totals;
}
private DomainList getDomains(String method, String idKey, String idValue, Date date, int perPage, int page) throws FlickrException {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("method", method);
parameters.put("date", String.valueOf(date.getTime() / 1000L));
if (idValue != null) {
parameters.put(idKey, idValue);
}
addPaginationParameters(parameters, perPage, page);
Response response = transportAPI.get(transportAPI.getPath(), parameters, apiKey, sharedSecret);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
DomainList domains = parseDomains(response);
return domains;
}
private DomainList parseDomains(Response response) {
Element element = response.getPayload();
DomainList domains = new DomainList();
domains.setPage(element.getAttribute("page"));
domains.setPages(element.getAttribute("pages"));
domains.setPerPage(element.getAttribute("perpage"));
domains.setTotal(element.getAttribute("total"));
NodeList domainElements = element.getElementsByTagName("domain");
for (int i = 0; i < domainElements.getLength(); i++) {
Element domainElement = (Element) domainElements.item(i);
Domain domain = new Domain();
domain.setName(domainElement.getAttribute("name"));
domain.setViews(domainElement.getAttribute("views"));
domains.add(domain);
}
return domains;
}
private ReferrerList getReferrers(String method, String domain, String idKey, String idValue, Date date, int perPage, int page) throws FlickrException {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("method", method);
parameters.put("domain", domain);
parameters.put("date", String.valueOf(date.getTime() / 1000L));
if (idValue != null) {
parameters.put(idKey, idValue);
}
addPaginationParameters(parameters, perPage, page);
Response response = transportAPI.get(transportAPI.getPath(), parameters, apiKey, sharedSecret);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
ReferrerList referrers = parseReferrers(response);
return referrers;
}
private ReferrerList parseReferrers(Response response) {
Element element = response.getPayload();
ReferrerList referrers = new ReferrerList();
referrers.setPage(element.getAttribute("page"));
referrers.setPages(element.getAttribute("pages"));
referrers.setPerPage(element.getAttribute("perpage"));
referrers.setTotal(element.getAttribute("total"));
referrers.setName(element.getAttribute("name"));
NodeList referrerElements = element.getElementsByTagName("referrer");
for (int i = 0; i < referrerElements.getLength(); i++) {
Element referrerElement = (Element) referrerElements.item(i);
Referrer referrer = new Referrer();
referrer.setUrl(referrerElement.getAttribute("url"));
referrer.setViews(referrerElement.getAttribute("views"));
referrers.add(referrer);
}
return referrers;
}
private Stats getStats(String method, String idKey, String idValue, Date date) throws FlickrException {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("method", method);
parameters.put("date", String.valueOf(date.getTime() / 1000L));
if (idValue != null) {
parameters.put(idKey, idValue);
}
Response response = transportAPI.get(transportAPI.getPath(), parameters, apiKey, sharedSecret);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
Stats stats = parseStats(response.getPayload());
return stats;
}
/**
*
* @param element
*/
private Stats parseStats(Element element) {
Stats stats = new Stats();
String views = element.getAttribute("views");
String comments = element.getAttribute("comments");
String favorites = element.getAttribute("favorites");
stats.setViews(views);
stats.setComments(comments);
stats.setFavorites(favorites);
return stats;
}
private Totals parseTotals(Response response) {
Element element = response.getPayload();
Totals stats = new Totals();
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element childElement = (Element) node;
String total = getViewsValue(childElement, "total");
if (total != null) {
stats.setTotal(total);
}
String photos = getViewsValue(childElement, "photos");
if (photos != null) {
stats.setPhotos(photos);
}
String photostream = getViewsValue(childElement, "photostream");
if (photostream != null) {
stats.setPhotostream(photostream);
}
String collections = getViewsValue(childElement, "collections");
if (collections != null) {
stats.setCollections(collections);
}
String sets = getViewsValue(childElement, "sets");
if (sets != null) {
stats.setSets(sets);
}
}
}
return stats;
}
private String getViewsValue(Element childElement, String name) {
String total = null;
if (childElement.getNodeName().equals(name)) {
total = childElement.getAttribute("views");
}
return total;
}
private void addPaginationParameters(Map<String, Object> parameters, int perPage, int page) {
if (perPage > 0) {
parameters.put("per_page", String.valueOf(perPage));
}
if (page > 0) {
parameters.put("page", String.valueOf(page));
}
}
private List<Csv> parseCsvFiles(Response response) {
Element element = response.getPayload();
List<Csv> csvFiles = new ArrayList<Csv>();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
NodeList csvElements = element.getElementsByTagName("csv");
for (int i = 0; i < csvElements.getLength(); i++) {
Element csvElement = (Element) csvElements.item(i);
Csv csv = new Csv();
csv.setHref(csvElement.getAttribute("href"));
csv.setType(csvElement.getAttribute("type"));
try {
csv.setDate(dateFormat.parse(csvElement.getAttribute("date")));
} catch (ParseException e) {
throw new FlickrRuntimeException(e);
}
csvFiles.add(csv);
}
return csvFiles;
}
/**
*
* @param response
*/
private PhotoList<Photo> parsePopularPhotos(Response response) {
Element payload = response.getPayload();
PhotoList<Photo> photos = new PhotoList<Photo>();
NodeList photoElements = payload.getElementsByTagName("photo");
for (int i = 0; i < photoElements.getLength(); i++) {
Element photoElement = (Element) photoElements.item(i);
Photo photo = PhotoUtils.createPhoto(photoElement);
Element statsElement = XMLUtilities.getChild(photoElement, "stats");
Stats stats = parseStats(statsElement);
photo.setStats(stats);
photos.add(photo);
}
return photos;
}
}