/* * Copyright (c) 2005 Aetrion LLC. */ package com.flickr4java.flickr.photos; import com.flickr4java.flickr.FlickrException; import com.flickr4java.flickr.REST; import com.flickr4java.flickr.RequestContext; import com.flickr4java.flickr.Response; import com.flickr4java.flickr.Transport; import com.flickr4java.flickr.people.User; import com.flickr4java.flickr.photos.geo.GeoInterface; import com.flickr4java.flickr.util.IOUtilities; import com.flickr4java.flickr.util.StringUtilities; import com.flickr4java.flickr.util.XMLUtilities; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import javax.imageio.ImageIO; import javax.net.ssl.HttpsURLConnection; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * Interface for working with Flickr Photos. * * @author Anthony Eden * @version $Id: PhotosInterface.java,v 1.51 2010/07/20 20:11:16 x-mago Exp $ */ public class PhotosInterface { public static final String METHOD_ADD_TAGS = "flickr.photos.addTags"; public static final String METHOD_DELETE = "flickr.photos.delete"; public static final String METHOD_GET_ALL_CONTEXTS = "flickr.photos.getAllContexts"; public static final String METHOD_GET_CONTACTS_PHOTOS = "flickr.photos.getContactsPhotos"; public static final String METHOD_GET_CONTACTS_PUBLIC_PHOTOS = "flickr.photos.getContactsPublicPhotos"; public static final String METHOD_GET_CONTEXT = "flickr.photos.getContext"; public static final String METHOD_GET_COUNTS = "flickr.photos.getCounts"; public static final String METHOD_GET_EXIF = "flickr.photos.getExif"; public static final String METHOD_GET_FAVORITES = "flickr.photos.getFavorites"; public static final String METHOD_GET_INFO = "flickr.photos.getInfo"; public static final String METHOD_GET_NOT_IN_SET = "flickr.photos.getNotInSet"; public static final String METHOD_GET_PERMS = "flickr.photos.getPerms"; public static final String METHOD_GET_RECENT = "flickr.photos.getRecent"; public static final String METHOD_GET_SIZES = "flickr.photos.getSizes"; public static final String METHOD_GET_UNTAGGED = "flickr.photos.getUntagged"; public static final String METHOD_GET_WITH_GEO_DATA = "flickr.photos.getWithGeoData"; public static final String METHOD_GET_WITHOUT_GEO_DATA = "flickr.photos.getWithoutGeoData"; public static final String METHOD_RECENTLY_UPDATED = "flickr.photos.recentlyUpdated"; public static final String METHOD_REMOVE_TAG = "flickr.photos.removeTag"; public static final String METHOD_SEARCH = "flickr.photos.search"; public static final String METHOD_SET_CONTENTTYPE = "flickr.photos.setContentType"; public static final String METHOD_SET_DATES = "flickr.photos.setDates"; public static final String METHOD_SET_META = "flickr.photos.setMeta"; public static final String METHOD_SET_PERMS = "flickr.photos.setPerms"; public static final String METHOD_SET_SAFETYLEVEL = "flickr.photos.setSafetyLevel"; public static final String METHOD_SET_TAGS = "flickr.photos.setTags"; public static final String METHOD_GET_INTERESTINGNESS = "flickr.interestingness.getList"; private static final ThreadLocal<SimpleDateFormat> DATE_FORMATS = new ThreadLocal<SimpleDateFormat>() { @Override protected synchronized SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } }; private GeoInterface geoInterface = null; private final String apiKey; private final String sharedSecret; private final Transport transport; public PhotosInterface(String apiKey, String sharedSecret, Transport transport) { this.apiKey = apiKey; this.sharedSecret = sharedSecret; this.transport = transport; } /** * Get the geo interface. * * @return Access class to the flickr.photos.geo methods. */ public synchronized GeoInterface getGeoInterface() { if (geoInterface == null) { geoInterface = new GeoInterface(apiKey, sharedSecret, transport); } return geoInterface; } /** * Add tags to a photo. * * This method requires authentication with 'write' permission. * * @param photoId * The photo ID * @param tags * The tags * @throws FlickrException */ public void addTags(String photoId, String[] tags) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_ADD_TAGS); parameters.put("photo_id", photoId); parameters.put("tags", StringUtilities.join(tags, " ", true)); Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Delete a photo from flickr. * * This method requires authentication with 'delete' permission. * * @param photoId * @throws FlickrException */ public void delete(String photoId) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_DELETE); parameters.put("photo_id", photoId); // Note: This method requires an HTTP POST request. Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } // This method has no specific response - It returns an empty // sucess response if it completes without error. } /** * Returns all visble sets and pools the photo belongs to. * * This method does not require authentication. * * @param photoId * The photo to return information for. * @return a list of {@link PhotoContext} objects * @throws FlickrException */ public PhotoAllContext getAllContexts(String photoId) throws FlickrException { PhotoSetList<PhotoSet> setList = new PhotoSetList<PhotoSet>(); PoolList<Pool> poolList = new PoolList<Pool>(); PhotoAllContext allContext = new PhotoAllContext(); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_ALL_CONTEXTS); parameters.put("photo_id", photoId); Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Collection<Element> photosElement = response.getPayloadCollection(); for (Element setElement : photosElement) { if (setElement.getTagName().equals("set")) { PhotoSet pset = new PhotoSet(); pset.setTitle(setElement.getAttribute("title")); pset.setSecret(setElement.getAttribute("secret")); pset.setId(setElement.getAttribute("id")); pset.setFarm(setElement.getAttribute("farm")); pset.setPrimary(setElement.getAttribute("primary")); pset.setServer(setElement.getAttribute("server")); pset.setViewCount(Integer.parseInt(setElement.getAttribute("view_count"))); pset.setCommentCount(Integer.parseInt(setElement.getAttribute("comment_count"))); pset.setCountPhoto(Integer.parseInt(setElement.getAttribute("count_photo"))); pset.setCountVideo(Integer.parseInt(setElement.getAttribute("count_video"))); setList.add(pset); allContext.setPhotoSetList(setList); } else if (setElement.getTagName().equals("pool")) { Pool pool = new Pool(); pool.setTitle(setElement.getAttribute("title")); pool.setId(setElement.getAttribute("id")); pool.setUrl(setElement.getAttribute("url")); pool.setIconServer(setElement.getAttribute("iconserver")); pool.setIconFarm(setElement.getAttribute("iconfarm")); pool.setMemberCount(Integer.parseInt(setElement.getAttribute("members"))); pool.setPoolCount(Integer.parseInt(setElement.getAttribute("pool_count"))); poolList.add(pool); allContext.setPoolList(poolList); } } return allContext; } /** * Get photos from the user's contacts. * * This method requires authentication with 'read' permission. * * @param count * The number of photos to return * @param justFriends * Set to true to only show friends photos * @param singlePhoto * Set to true to get a single photo * @param includeSelf * Set to true to include self * @return The Collection of photos * @throws FlickrException */ public PhotoList<Photo> getContactsPhotos(int count, boolean justFriends, boolean singlePhoto, boolean includeSelf) throws FlickrException { PhotoList<Photo> photos = new PhotoList<Photo>(); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_CONTACTS_PHOTOS); if (count > 0) { parameters.put("count", Integer.toString(count)); } if (justFriends) { parameters.put("just_friends", "1"); } if (singlePhoto) { parameters.put("single_photo", "1"); } if (includeSelf) { parameters.put("include_self", "1"); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photosElement = response.getPayload(); NodeList photoNodes = photosElement.getElementsByTagName("photo"); photos.setPage("1"); photos.setPages("1"); photos.setPerPage("" + photoNodes.getLength()); photos.setTotal("" + photoNodes.getLength()); for (int i = 0; i < photoNodes.getLength(); i++) { Element photoElement = (Element) photoNodes.item(i); photos.add(PhotoUtils.createPhoto(photoElement)); } return photos; } /** * Get public photos from the user's contacts. * * This method does not require authentication. * * @see com.flickr4java.flickr.photos.Extras * @param userId * The user ID * @param count * The number of photos to return * @param justFriends * True to include friends * @param singlePhoto * True to get a single photo * @param includeSelf * True to include self * @return A collection of Photo objects * @throws FlickrException */ public PhotoList<Photo> getContactsPublicPhotos(String userId, int count, boolean justFriends, boolean singlePhoto, boolean includeSelf) throws FlickrException { return getContactsPublicPhotos(userId, Extras.MIN_EXTRAS, count, justFriends, singlePhoto, includeSelf); } public PhotoList<Photo> getContactsPublicPhotos(String userId, Set<String> extras, int count, boolean justFriends, boolean singlePhoto, boolean includeSelf) throws FlickrException { PhotoList<Photo> photos = new PhotoList<Photo>(); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_CONTACTS_PUBLIC_PHOTOS); parameters.put("user_id", userId); if (count > 0) { parameters.put("count", Integer.toString(count)); } if (justFriends) { parameters.put("just_friends", "1"); } if (singlePhoto) { parameters.put("single_photo", "1"); } if (includeSelf) { parameters.put("include_self", "1"); } if (extras != null) { StringBuffer sb = new StringBuffer(); Iterator<String> it = extras.iterator(); for (int i = 0; it.hasNext(); i++) { if (i > 0) { sb.append(","); } sb.append(it.next()); } parameters.put(Extras.KEY_EXTRAS, sb.toString()); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photosElement = response.getPayload(); NodeList photoNodes = photosElement.getElementsByTagName("photo"); photos.setPage("1"); photos.setPages("1"); photos.setPerPage("" + photoNodes.getLength()); photos.setTotal("" + photoNodes.getLength()); for (int i = 0; i < photoNodes.getLength(); i++) { Element photoElement = (Element) photoNodes.item(i); photos.add(PhotoUtils.createPhoto(photoElement)); } return photos; } /** * Get the context for the specified photo. * * This method does not require authentication. * * @param photoId * The photo ID * @return The PhotoContext * @throws FlickrException */ public PhotoContext getContext(String photoId) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_CONTEXT); parameters.put("photo_id", photoId); Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } PhotoContext photoContext = new PhotoContext(); Collection<Element> payload = response.getPayloadCollection(); for (Element payloadElement : payload) { String tagName = payloadElement.getTagName(); if (tagName.equals("prevphoto")) { Photo photo = new Photo(); photo.setId(payloadElement.getAttribute("id")); photo.setSecret(payloadElement.getAttribute("secret")); photo.setTitle(payloadElement.getAttribute("title")); photo.setFarm(payloadElement.getAttribute("farm")); photo.setUrl(payloadElement.getAttribute("url")); photoContext.setPreviousPhoto(photo); } else if (tagName.equals("nextphoto")) { Photo photo = new Photo(); photo.setId(payloadElement.getAttribute("id")); photo.setSecret(payloadElement.getAttribute("secret")); photo.setTitle(payloadElement.getAttribute("title")); photo.setFarm(payloadElement.getAttribute("farm")); photo.setUrl(payloadElement.getAttribute("url")); photoContext.setNextPhoto(photo); } } return photoContext; } /** * Gets a collection of photo counts for the given date ranges for the calling user. * * This method requires authentication with 'read' permission. * * @param dates * An array of dates, denoting the periods to return counts for. They should be specified smallest first. * @param takenDates * An array of dates, denoting the periods to return counts for. They should be specified smallest first. * @return A Collection of Photocount objects */ public Collection<Photocount> getCounts(Date[] dates, Date[] takenDates) throws FlickrException { List<Photocount> photocounts = new ArrayList<Photocount>(); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_COUNTS); if (dates == null && takenDates == null) { throw new IllegalArgumentException("You must provide a value for either dates or takenDates"); } if (dates != null) { List<String> dateList = new ArrayList<String>(); for (int i = 0; i < dates.length; i++) { dateList.add(String.valueOf(dates[i].getTime() / 1000L)); } parameters.put("dates", StringUtilities.join(dateList, ",")); } if (takenDates != null) { List<String> takenDateList = new ArrayList<String>(); for (int i = 0; i < takenDates.length; i++) { takenDateList.add(String.valueOf(takenDates[i].getTime() / 1000L)); } parameters.put("taken_dates", StringUtilities.join(takenDateList, ",")); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photocountsElement = response.getPayload(); NodeList photocountNodes = photocountsElement.getElementsByTagName("photocount"); for (int i = 0; i < photocountNodes.getLength(); i++) { Element photocountElement = (Element) photocountNodes.item(i); Photocount photocount = new Photocount(); photocount.setCount(photocountElement.getAttribute("count")); photocount.setFromDate(photocountElement.getAttribute("fromdate")); photocount.setToDate(photocountElement.getAttribute("todate")); photocounts.add(photocount); } return photocounts; } /** * Get the Exif data for the photo. * * The calling user must have permission to view the photo. * * This method does not require authentication. * * @param photoId * The photo ID * @param secret * The secret * @return A collection of Exif objects * @throws FlickrException */ public Collection<Exif> getExif(String photoId, String secret) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_EXIF); parameters.put("photo_id", photoId); if (secret != null) { parameters.put("secret", secret); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } List<Exif> exifs = new ArrayList<Exif>(); Element photoElement = response.getPayload(); NodeList exifElements = photoElement.getElementsByTagName("exif"); for (int i = 0; i < exifElements.getLength(); i++) { Element exifElement = (Element) exifElements.item(i); Exif exif = new Exif(); exif.setTagspace(exifElement.getAttribute("tagspace")); exif.setTagspaceId(exifElement.getAttribute("tagspaceid")); exif.setTag(exifElement.getAttribute("tag")); exif.setLabel(exifElement.getAttribute("label")); exif.setRaw(XMLUtilities.getChildValue(exifElement, "raw")); exif.setClean(XMLUtilities.getChildValue(exifElement, "clean")); exifs.add(exif); } return exifs; } /** * Returns the list of people who have favorited a given photo. * * This method does not require authentication. * * @param photoId * @param perPage * @param page * @return List of {@link com.flickr4java.flickr.people.User} */ public Collection<User> getFavorites(String photoId, int perPage, int page) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_FAVORITES); parameters.put("photo_id", photoId); if (perPage > 0) { parameters.put("per_page", Integer.toString(perPage)); } if (page > 0) { parameters.put("page", Integer.toString(page)); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } List<User> users = new ArrayList<User>(); Element userRoot = response.getPayload(); NodeList userNodes = userRoot.getElementsByTagName("person"); for (int i = 0; i < userNodes.getLength(); i++) { Element userElement = (Element) userNodes.item(i); User user = new User(); user.setId(userElement.getAttribute("nsid")); user.setUsername(userElement.getAttribute("username")); user.setFaveDate(userElement.getAttribute("favedate")); users.add(user); } return users; } /** * Get all info for the specified photo. * * The calling user must have permission to view the photo. * * This method does not require authentication. * * @param photoId * The photo Id * @param secret * The optional secret String * @return The Photo * @throws FlickrException */ public Photo getInfo(String photoId, String secret) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_INFO); parameters.put("photo_id", photoId); if (secret != null) { parameters.put("secret", secret); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photoElement = response.getPayload(); return PhotoUtils.createPhoto(photoElement); } /** * Return a collection of Photo objects not in part of any sets. * * This method requires authentication with 'read' permission. * * @param perPage * The per page * @param page * The page * @return The collection of Photo objects * @throws FlickrException */ public PhotoList<Photo> getNotInSet(int perPage, int page) throws FlickrException { PhotoList<Photo> photos = new PhotoList<Photo>(); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", PhotosInterface.METHOD_GET_NOT_IN_SET); RequestContext requestContext = RequestContext.getRequestContext(); List<String> extras = requestContext.getExtras(); if (extras.size() > 0) { parameters.put("extras", StringUtilities.join(extras, ",")); } if (perPage > 0) { parameters.put("per_page", Integer.toString(perPage)); } if (page > 0) { parameters.put("page", Integer.toString(page)); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photosElement = response.getPayload(); photos.setPage(photosElement.getAttribute("page")); photos.setPages(photosElement.getAttribute("pages")); photos.setPerPage(photosElement.getAttribute("perpage")); photos.setTotal(photosElement.getAttribute("total")); NodeList photoElements = photosElement.getElementsByTagName("photo"); for (int i = 0; i < photoElements.getLength(); i++) { Element photoElement = (Element) photoElements.item(i); photos.add(PhotoUtils.createPhoto(photoElement)); } return photos; } /** * Get the permission information for the specified photo. * * This method requires authentication with 'read' permission. * * @param photoId * The photo id * @return The Permissions object * @throws FlickrException */ public Permissions getPerms(String photoId) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_PERMS); parameters.put("photo_id", photoId); Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element permissionsElement = response.getPayload(); Permissions permissions = new Permissions(); permissions.setId(permissionsElement.getAttribute("id")); permissions.setPublicFlag("1".equals(permissionsElement.getAttribute("ispublic"))); permissions.setFamilyFlag("1".equals(permissionsElement.getAttribute("isfamily"))); permissions.setFriendFlag("1".equals(permissionsElement.getAttribute("isfriend"))); permissions.setComment(permissionsElement.getAttribute("permcomment")); permissions.setAddmeta(permissionsElement.getAttribute("permaddmeta")); return permissions; } /** * Get a collection of recent photos. * * This method does not require authentication. * * @see com.flickr4java.flickr.photos.Extras * @param extras * Set of extra-fields * @param perPage * The number of photos per page * @param page * The page offset * @return A collection of Photo objects * @throws FlickrException */ public PhotoList<Photo> getRecent(Set<String> extras, int perPage, int page) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_RECENT); if (extras != null && !extras.isEmpty()) { parameters.put(Extras.KEY_EXTRAS, StringUtilities.join(extras, ",")); } if (perPage > 0) { parameters.put("per_page", Integer.toString(perPage)); } if (page > 0) { parameters.put("page", Integer.toString(page)); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photosElement = response.getPayload(); PhotoList<Photo> photos = PhotoUtils.createPhotoList(photosElement); return photos; } /** * Get the available sizes of a Photo. * * The calling user must have permission to view the photo. * * This method uses no authentication. * * @param photoId * The photo ID * @return A collection of {@link Size} * @throws FlickrException */ public Collection<Size> getSizes(String photoId) throws FlickrException { return getSizes(photoId, false); } /** * Get the available sizes of a Photo. * * The boolean toggle allows to (api-)sign the call. * * This way the calling user can retrieve sizes for <b>his own</b> private photos. * * @param photoId * The photo ID * @param sign * toggle to allow optionally signing the call (Authenticate) * @return A collection of {@link Size} * @throws FlickrException */ public Collection<Size> getSizes(String photoId, boolean sign) throws FlickrException { SizeList<Size> sizes = new SizeList<Size>(); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_SIZES); parameters.put("photo_id", photoId); Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element sizesElement = response.getPayload(); sizes.setIsCanBlog("1".equals(sizesElement.getAttribute("canblog"))); sizes.setIsCanDownload("1".equals(sizesElement.getAttribute("candownload"))); sizes.setIsCanPrint("1".equals(sizesElement.getAttribute("canprint"))); NodeList sizeNodes = sizesElement.getElementsByTagName("size"); for (int i = 0; i < sizeNodes.getLength(); i++) { Element sizeElement = (Element) sizeNodes.item(i); Size size = new Size(); size.setLabel(sizeElement.getAttribute("label")); size.setWidth(sizeElement.getAttribute("width")); size.setHeight(sizeElement.getAttribute("height")); size.setSource(sizeElement.getAttribute("source")); size.setUrl(sizeElement.getAttribute("url")); size.setMedia(sizeElement.getAttribute("media")); sizes.add(size); } return sizes; } /** * Get the collection of untagged photos. * * This method requires authentication with 'read' permission. * * @param perPage * @param page * @return A Collection of Photos * @throws FlickrException */ public PhotoList<Photo> getUntagged(int perPage, int page) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_UNTAGGED); if (perPage > 0) { parameters.put("per_page", Integer.toString(perPage)); } if (page > 0) { parameters.put("page", Integer.toString(page)); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photosElement = response.getPayload(); PhotoList<Photo> photos = PhotoUtils.createPhotoList(photosElement); return photos; } /** * Returns a list of your geo-tagged photos. * * This method requires authentication with 'read' permission. * * @param minUploadDate * Minimum upload date. Photos with an upload date greater than or equal to this value will be returned. Set to null to not specify a date. * @param maxUploadDate * Maximum upload date. Photos with an upload date less than or equal to this value will be returned. Set to null to not specify a date. * @param minTakenDate * Minimum taken date. Photos with an taken date greater than or equal to this value will be returned. Set to null to not specify a date. * @param maxTakenDate * Maximum taken date. Photos with an taken date less than or equal to this value will be returned. Set to null to not specify a date. * @param privacyFilter * Return photos only matching a certain privacy level. Valid values are: * <ul> * <li>1 public photos</li> * <li>2 private photos visible to friends</li> * <li>3 private photos visible to family</li> * <li>4 private photos visible to friends & family</li> * <li>5 completely private photos</li> * </ul> * Set to 0 to not specify a privacy Filter. * * @see com.flickr4java.flickr.photos.Extras * @param sort * The order in which to sort returned photos. Deafults to date-posted-desc. The possible values are: date-posted-asc, date-posted-desc, * date-taken-asc, date-taken-desc, interestingness-desc, and interestingness-asc. * @param extras * A set of Strings controlling the extra information to fetch for each returned record. Currently supported fields are: license, date_upload, * date_taken, owner_name, icon_server, original_format, last_update, geo. Set to null or an empty set to not specify any extras. * @param perPage * Number of photos to return per page. If this argument is 0, it defaults to 100. The maximum allowed value is 500. * @param page * The page of results to return. If this argument is 0, it defaults to 1. * @return photos * @throws FlickrException */ public PhotoList<Photo> getWithGeoData(Date minUploadDate, Date maxUploadDate, Date minTakenDate, Date maxTakenDate, int privacyFilter, String sort, Set<String> extras, int perPage, int page) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_WITH_GEO_DATA); if (minUploadDate != null) { parameters.put("min_upload_date", Long.toString(minUploadDate.getTime() / 1000L)); } if (maxUploadDate != null) { parameters.put("max_upload_date", Long.toString(maxUploadDate.getTime() / 1000L)); } if (minTakenDate != null) { parameters.put("min_taken_date", Long.toString(minTakenDate.getTime() / 1000L)); } if (maxTakenDate != null) { parameters.put("max_taken_date", Long.toString(maxTakenDate.getTime() / 1000L)); } if (privacyFilter > 0) { parameters.put("privacy_filter", Integer.toString(privacyFilter)); } if (sort != null) { parameters.put("sort", sort); } if (extras != null && !extras.isEmpty()) { parameters.put("extras", StringUtilities.join(extras, ",")); } if (perPage > 0) { parameters.put("per_page", Integer.toString(perPage)); } if (page > 0) { parameters.put("page", Integer.toString(page)); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photosElement = response.getPayload(); PhotoList<Photo> photos = PhotoUtils.createPhotoList(photosElement); return photos; } /** * Returns a list of your photos which haven't been geo-tagged. * * This method requires authentication with 'read' permission. * * @param minUploadDate * Minimum upload date. Photos with an upload date greater than or equal to this value will be returned. Set to null to not specify a date. * @param maxUploadDate * Maximum upload date. Photos with an upload date less than or equal to this value will be returned. Set to null to not specify a date. * @param minTakenDate * Minimum taken date. Photos with an taken date greater than or equal to this value will be returned. Set to null to not specify a date. * @param maxTakenDate * Maximum taken date. Photos with an taken date less than or equal to this value will be returned. Set to null to not specify a date. * @param privacyFilter * Return photos only matching a certain privacy level. Valid values are: * <ul> * <li>1 public photos</li> * <li>2 private photos visible to friends</li> * <li>3 private photos visible to family</li> * <li>4 private photos visible to friends & family</li> * <li>5 completely private photos</li> * </ul> * Set to 0 to not specify a privacy Filter. * * @see com.flickr4java.flickr.photos.Extras * @param sort * The order in which to sort returned photos. Deafults to date-posted-desc. The possible values are: date-posted-asc, date-posted-desc, * date-taken-asc, date-taken-desc, interestingness-desc, and interestingness-asc. * @param extras * A set of Strings controlling the extra information to fetch for each returned record. Currently supported fields are: license, date_upload, * date_taken, owner_name, icon_server, original_format, last_update, geo. Set to null or an empty set to not specify any extras. * @param perPage * Number of photos to return per page. If this argument is 0, it defaults to 100. The maximum allowed value is 500. * @param page * The page of results to return. If this argument is 0, it defaults to 1. * @return a photo list * @throws FlickrException */ public PhotoList<Photo> getWithoutGeoData(Date minUploadDate, Date maxUploadDate, Date minTakenDate, Date maxTakenDate, int privacyFilter, String sort, Set<String> extras, int perPage, int page) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_WITHOUT_GEO_DATA); if (minUploadDate != null) { parameters.put("min_upload_date", Long.toString(minUploadDate.getTime() / 1000L)); } if (maxUploadDate != null) { parameters.put("max_upload_date", Long.toString(maxUploadDate.getTime() / 1000L)); } if (minTakenDate != null) { parameters.put("min_taken_date", Long.toString(minTakenDate.getTime() / 1000L)); } if (maxTakenDate != null) { parameters.put("max_taken_date", Long.toString(maxTakenDate.getTime() / 1000L)); } if (privacyFilter > 0) { parameters.put("privacy_filter", Long.toString(privacyFilter)); } if (sort != null) { parameters.put("sort", sort); } if (extras != null && !extras.isEmpty()) { parameters.put("extras", StringUtilities.join(extras, ",")); } if (perPage > 0) { parameters.put("per_page", Integer.toString(perPage)); } if (page > 0) { parameters.put("page", Integer.toString(page)); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photosElement = response.getPayload(); PhotoList<Photo> photos = PhotoUtils.createPhotoList(photosElement); return photos; } /** * Return a list of your photos that have been recently created or which have been recently modified. Recently modified may mean that the photo's metadata * (title, description, tags) may have been changed or a comment has been added (or just modified somehow :-) * * This method requires authentication with 'read' permission. * * @see com.flickr4java.flickr.photos.Extras * @param minDate * Date indicating the date from which modifications should be compared. Must be given. * @param extras * A set of Strings controlling the extra information to fetch for each returned record. Currently supported fields are: license, date_upload, * date_taken, owner_name, icon_server, original_format, last_update, geo. Set to null or an empty set to not specify any extras. * @param perPage * Number of photos to return per page. If this argument is 0, it defaults to 100. The maximum allowed value is 500. * @param page * The page of results to return. If this argument is 0, it defaults to 1. * @return a list of photos * @throws FlickrException */ public PhotoList<Photo> recentlyUpdated(Date minDate, Set<String> extras, int perPage, int page) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_RECENTLY_UPDATED); parameters.put("min_date", Long.toString(minDate.getTime() / 1000L)); if (extras != null && !extras.isEmpty()) { parameters.put("extras", StringUtilities.join(extras, ",")); } if (perPage > 0) { parameters.put("per_page", Integer.toString(perPage)); } if (page > 0) { parameters.put("page", Integer.toString(page)); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photosElement = response.getPayload(); PhotoList<Photo> photos = PhotoUtils.createPhotoList(photosElement); return photos; } /** * Remove a tag from a photo. * * This method requires authentication with 'write' permission. * * @param tagId * The tag ID * @throws FlickrException */ public void removeTag(String tagId) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_REMOVE_TAG); parameters.put("tag_id", tagId); Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Search for photos which match the given search parameters. * * @param params * The search parameters * @param perPage * The number of photos to show per page * @param page * The page offset * @return A PhotoList * @throws FlickrException */ public PhotoList<Photo> search(SearchParameters params, int perPage, int page) throws FlickrException { PhotoList<Photo> photos = new PhotoList<Photo>(); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_SEARCH); parameters.putAll(params.getAsParameters()); if (perPage > 0) { parameters.put("per_page", "" + perPage); } if (page > 0) { parameters.put("page", "" + page); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photosElement = response.getPayload(); photos.setPage(photosElement.getAttribute("page")); photos.setPages(photosElement.getAttribute("pages")); photos.setPerPage(photosElement.getAttribute("perpage")); photos.setTotal(photosElement.getAttribute("total")); NodeList photoNodes = photosElement.getElementsByTagName("photo"); for (int i = 0; i < photoNodes.getLength(); i++) { Element photoElement = (Element) photoNodes.item(i); photos.add(PhotoUtils.createPhoto(photoElement)); } return photos; } /** * Search for interesting photos using the Flickr Interestingness algorithm. * * @param params * Any search parameters * @param perPage * Number of items per page * @param page * The page to start on * @return A PhotoList * @throws FlickrException */ public PhotoList<Photo> searchInterestingness(SearchParameters params, int perPage, int page) throws FlickrException { PhotoList<Photo> photos = new PhotoList<Photo>(); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_INTERESTINGNESS); parameters.putAll(params.getAsParameters()); if (perPage > 0) { parameters.put("per_page", Integer.toString(perPage)); } if (page > 0) { parameters.put("page", Integer.toString(page)); } Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } Element photosElement = response.getPayload(); photos.setPage(photosElement.getAttribute("page")); photos.setPages(photosElement.getAttribute("pages")); photos.setPerPage(photosElement.getAttribute("perpage")); photos.setTotal(photosElement.getAttribute("total")); NodeList photoNodes = photosElement.getElementsByTagName("photo"); for (int i = 0; i < photoNodes.getLength(); i++) { Element photoElement = (Element) photoNodes.item(i); Photo photo = new Photo(); photo.setId(photoElement.getAttribute("id")); User owner = new User(); owner.setId(photoElement.getAttribute("owner")); photo.setOwner(owner); photo.setSecret(photoElement.getAttribute("secret")); photo.setServer(photoElement.getAttribute("server")); photo.setFarm(photoElement.getAttribute("farm")); photo.setTitle(photoElement.getAttribute("title")); photo.setPublicFlag("1".equals(photoElement.getAttribute("ispublic"))); photo.setFriendFlag("1".equals(photoElement.getAttribute("isfriend"))); photo.setFamilyFlag("1".equals(photoElement.getAttribute("isfamily"))); photos.add(photo); } return photos; } /** * Set the content type of a photo. * * This method requires authentication with 'write' permission. * * @see com.flickr4java.flickr.Flickr#CONTENTTYPE_PHOTO * @see com.flickr4java.flickr.Flickr#CONTENTTYPE_SCREENSHOT * @see com.flickr4java.flickr.Flickr#CONTENTTYPE_OTHER * @param photoId * The photo ID * @param contentType * The contentType to set * @throws FlickrException */ public void setContentType(String photoId, String contentType) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_SET_CONTENTTYPE); parameters.put("photo_id", photoId); parameters.put("content_type", contentType); Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Set the dates for the specified photo. * * This method requires authentication with 'write' permission. * * @param photoId * The photo ID * @param datePosted * The date the photo was posted or null * @param dateTaken * The date the photo was taken or null * @param dateTakenGranularity * The granularity of the taken date or null * @throws FlickrException */ public void setDates(String photoId, Date datePosted, Date dateTaken, String dateTakenGranularity) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_SET_DATES); parameters.put("photo_id", photoId); if (datePosted != null) { parameters.put("date_posted", Long.toString(datePosted.getTime() / 1000)); } if (dateTaken != null) { parameters.put("date_taken", ((DateFormat) DATE_FORMATS.get()).format(dateTaken)); } if (dateTakenGranularity != null) { parameters.put("date_taken_granularity", dateTakenGranularity); } Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Set the meta data for the photo. * * This method requires authentication with 'write' permission. * * @param photoId * The photo ID * @param title * The new title * @param description * The new description * @throws FlickrException */ public void setMeta(String photoId, String title, String description) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_SET_META); parameters.put("photo_id", photoId); parameters.put("title", title); parameters.put("description", description); Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Set the permissions for the photo. * * This method requires authentication with 'write' permission. * * @param photoId * The photo ID * @param permissions * The permissions object * @throws FlickrException */ public void setPerms(String photoId, Permissions permissions) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_SET_PERMS); parameters.put("photo_id", photoId); parameters.put("is_public", permissions.isPublicFlag() ? "1" : "0"); parameters.put("is_friend", permissions.isFriendFlag() ? "1" : "0"); parameters.put("is_family", permissions.isFamilyFlag() ? "1" : "0"); parameters.put("perm_comment", Integer.toString(permissions.getComment())); parameters.put("perm_addmeta", Integer.toString(permissions.getAddmeta())); Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Set the safety level (adultness) of a photo. * <p> * * This method requires authentication with 'write' permission. * * @param photoId * The photo ID * @param safetyLevel * The safety level of the photo or null * @param hidden * Hidden from public searches or not or null * @see com.flickr4java.flickr.Flickr#SAFETYLEVEL_SAFE * @see com.flickr4java.flickr.Flickr#SAFETYLEVEL_MODERATE * @see com.flickr4java.flickr.Flickr#SAFETYLEVEL_RESTRICTED * @throws FlickrException */ public void setSafetyLevel(String photoId, String safetyLevel, Boolean hidden) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_SET_SAFETYLEVEL); parameters.put("photo_id", photoId); if (safetyLevel != null) { parameters.put("safety_level", safetyLevel); } if (hidden != null) { parameters.put("hidden", hidden.booleanValue() ? "1" : "0"); } Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Set the tags for a photo. * * This method requires authentication with 'write' permission. * * @param photoId * The photo ID * @param tags * The tag array * @throws FlickrException */ public void setTags(String photoId, String[] tags) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_SET_TAGS); parameters.put("photo_id", photoId); parameters.put("tags", StringUtilities.join(tags, " ", true)); Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Get the photo for the specified ID. Currently maps to the getInfo() method. * * @param id * The ID * @return The Photo */ public Photo getPhoto(String id) throws FlickrException { return getPhoto(id, null); } /** * Get the photo for the specified ID with the given secret. Currently maps to the getInfo() method. * * @param id * The ID * @param secret * The secret * @return The Photo */ public Photo getPhoto(String id, String secret) throws FlickrException { return getInfo(id, secret); } /** * Request an image from the Flickr-servers.<br> * Callers must close the stream upon completion. * <p> * * At {@link Size} you can find constants for the available sizes. * * @param photo * A photo-object * @param size * The Size * @return InputStream The InputStream * @throws FlickrException */ public InputStream getImageAsStream(Photo photo, int size) throws FlickrException { try { String urlStr = ""; if (size == Size.SQUARE) { urlStr = photo.getSmallSquareUrl(); } else if (size == Size.THUMB) { urlStr = photo.getThumbnailUrl(); } else if (size == Size.SMALL) { urlStr = photo.getSmallUrl(); } else if (size == Size.MEDIUM) { urlStr = photo.getMediumUrl(); } else if (size == Size.LARGE) { urlStr = photo.getLargeUrl(); } else if (size == Size.LARGE_1600) { urlStr = photo.getLarge1600Url(); } else if (size == Size.LARGE_2048) { urlStr = photo.getLarge2048Url(); } else if (size == Size.ORIGINAL) { urlStr = photo.getOriginalUrl(); } else if (size == Size.SQUARE_LARGE) { urlStr = photo.getSquareLargeUrl(); } else if (size == Size.SMALL_320) { urlStr = photo.getSmall320Url(); } else if (size == Size.MEDIUM_640) { urlStr = photo.getMedium640Url(); } else if (size == Size.MEDIUM_800) { urlStr = photo.getMedium800Url(); } else if (size == Size.VIDEO_ORIGINAL) { urlStr = photo.getVideoOriginalUrl(); } else if (size == Size.VIDEO_PLAYER) { urlStr = photo.getVideoPlayerUrl(); } else if (size == Size.SITE_MP4) { urlStr = photo.getSiteMP4Url(); } else if (size == Size.MOBILE_MP4) { urlStr = photo.getMobileMp4Url(); } else if (size == Size.HD_MP4) { urlStr = photo.getHdMp4Url(); } else { throw new FlickrException("0", "Unknown Photo-size"); } URL url = new URL(urlStr); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); if (transport instanceof REST) { if (((REST) transport).isProxyAuth()) { conn.setRequestProperty("Proxy-Authorization", "Basic " + ((REST) transport).getProxyCredentials()); } } conn.connect(); return conn.getInputStream(); } catch (IOException e) { throw new FlickrException(e.getMessage(), e.getCause()); } } /** * Request an image from the Flickr-servers. * <p> * * At {@link Size} you can find constants for the available sizes. * * @param photo * A photo-object * @param size * The size * @return An Image * @throws FlickrException */ public BufferedImage getImage(Photo photo, int size) throws FlickrException { try { return ImageIO.read(getImageAsStream(photo, size)); } catch (IOException e) { throw new FlickrException(e.getMessage(), e.getCause()); } } /** * Download of an image by URL. * * @param urlStr * The URL of a Photo * @return BufferedImage The The Image */ public BufferedImage getImage(String urlStr) throws FlickrException { InputStream in = null; try { URL url = new URL(urlStr); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); if (transport instanceof REST) { if (((REST) transport).isProxyAuth()) { conn.setRequestProperty("Proxy-Authorization", "Basic " + ((REST) transport).getProxyCredentials()); } } conn.connect(); in = conn.getInputStream(); return ImageIO.read(in); } catch (IOException e) { throw new FlickrException(e.getMessage(), e.getCause()); } finally { IOUtilities.close(in); } } }