package com.flickr4java.flickr.photos.geo; import com.flickr4java.flickr.FlickrException; import com.flickr4java.flickr.Response; import com.flickr4java.flickr.Transport; import com.flickr4java.flickr.photos.GeoData; import com.flickr4java.flickr.photos.Photo; import com.flickr4java.flickr.photos.PhotoList; import com.flickr4java.flickr.photos.PhotoUtils; import com.flickr4java.flickr.util.StringUtilities; import com.flickr4java.flickr.util.XMLUtilities; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * Access to the flickr.photos.geo methods. * * @author till (Till Krech - flickr:extranoise) * @version $Id: GeoInterface.java,v 1.5 2009/07/22 22:39:36 x-mago Exp $ */ public class GeoInterface { public static final String METHOD_GET_LOCATION = "flickr.photos.geo.getLocation"; public static final String METHOD_GET_PERMS = "flickr.photos.geo.getPerms"; public static final String METHOD_REMOVE_LOCATION = "flickr.photos.geo.removeLocation"; public static final String METHOD_SET_LOCATION = "flickr.photos.geo.setLocation"; public static final String METHOD_SET_PERMS = "flickr.photos.geo.setPerms"; public static final String METHOD_BATCH_CORRECT_LOCATION = "flickr.photos.geo.batchCorrectLocation"; public static final String METHOD_CORRECT_LOCATION = "flickr.photos.geo.correctLocation"; public static final String METHOD_PHOTOS_FOR_LOCATION = "flickr.photos.geo.photosForLocation"; public static final String METHOD_SET_CONTEXT = "flickr.photos.geo.setContext"; private final String apiKey; private final String sharedSecret; private final Transport transport; public GeoInterface(String apiKey, String sharedSecret, Transport transport) { this.apiKey = apiKey; this.sharedSecret = sharedSecret; this.transport = transport; } /** * Get the geo data (latitude and longitude and the accuracy level) for a photo. * * This method does not require authentication. * * @param photoId * reqired photo id, not null * @return Geo Data, if the photo has it. * @throws FlickrException * if photo id is invalid, if photo has no geodata or if any other error has been reported in the response. */ public GeoData getLocation(String photoId) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_GET_LOCATION); parameters.put("photo_id", photoId); Response response = transport.get(transport.getPath(), parameters, apiKey, sharedSecret); if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } // response: // <photo id="123"> // <location latitude="-17.685895" longitude="-63.36914" accuracy="6" /> // </photo> Element photoElement = response.getPayload(); Element locationElement = XMLUtilities.getChild(photoElement, "location"); String latStr = locationElement.getAttribute("latitude"); String lonStr = locationElement.getAttribute("longitude"); String accStr = locationElement.getAttribute("accuracy"); // I ignore the id attribute. should be the same as the given // photo id. GeoData geoData = new GeoData(lonStr, latStr, accStr); return geoData; } /** * Get permissions for who may view geo data for a photo. * * This method requires authentication with 'read' permission. * * @param photoId * reqired photo id, not null * @return the permissions * @throws FlickrException * if photo id is invalid, if photo has no geodata or if any other error has been reported in the response. */ public GeoPermissions 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()); } // response: // <perms id="240935723" ispublic="1" iscontact="0" isfriend="0" isfamily="0"/> GeoPermissions perms = new GeoPermissions(); Element permsElement = response.getPayload(); perms.setPublic("1".equals(permsElement.getAttribute("ispublic"))); perms.setContact("1".equals(permsElement.getAttribute("iscontact"))); perms.setFriend("1".equals(permsElement.getAttribute("isfriend"))); perms.setFamily("1".equals(permsElement.getAttribute("isfamily"))); perms.setId(permsElement.getAttribute("id")); // I ignore the id attribute. should be the same as the given // photo id. return perms; } /** * Removes the geo data associated with a photo. * * This method requires authentication with 'write' permission. * * @throws FlickrException */ public void removeLocation(String photoId) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_REMOVE_LOCATION); parameters.put("photo_id", photoId); // Note: This method requires an HTTP POST request. Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); // This method has no specific response - It returns an empty sucess response // if it completes without error. if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Sets the geo data (latitude and longitude and, optionally, the accuracy level) for a photo. Before users may assign location data to a photo they must * define who, by default, may view that information. Users can edit this preference at <a href="http://www.flickr.com/account/geo/privacy/">flickr</a>. If * a user has not set this preference, the API method will return an error. * * This method requires authentication with 'write' permission. * * @param photoId * The id of the photo to cet permissions for. * @param location * geo data with optional accuracy (1-16), accuracy 0 to use the default. * @throws FlickrException */ public void setLocation(String photoId, GeoData location) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_SET_LOCATION); parameters.put("photo_id", photoId); parameters.put("lat", String.valueOf(location.getLatitude())); parameters.put("lon", String.valueOf(location.getLongitude())); int accuracy = location.getAccuracy(); if (accuracy > 0) { parameters.put("accuracy", String.valueOf(location.getAccuracy())); } // Note: This method requires an HTTP POST request. Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); // This method has no specific response - It returns an empty sucess response // if it completes without error. if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Set the permission for who may view the geo data associated with a photo. * * This method requires authentication with 'write' permission. * * @param photoId * The id of the photo to set permissions for. * @param perms * Permissions, who can see the geo data of this photo * @throws FlickrException */ public void setPerms(String photoId, GeoPermissions perms) 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", perms.isPublic() ? "1" : "0"); parameters.put("is_contact", perms.isContact() ? "1" : "0"); parameters.put("is_friend", perms.isFriend() ? "1" : "0"); parameters.put("is_family", perms.isFamily() ? "1" : "0"); // Note: This method requires an HTTP POST request. Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); // This method has no specific response - It returns an empty sucess response // if it completes without error. if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Correct the places hierarchy for all the photos for a user at a given latitude, longitude and accuracy. * <p> * * Batch corrections are processed in a delayed queue so it may take a few minutes before the changes are reflected in a user's photos. * * @param location * The latitude/longitude and accuracy of the photos to be update. * @param placeId * A Flickr Places ID. (While optional, you must pass either a valid Places ID or a WOE ID.) * @param woeId * A Where On Earth (WOE) ID. (While optional, you must pass either a valid Places ID or a WOE ID.) * @throws FlickrException */ public void batchCorrectLocation(GeoData location, String placeId, String woeId) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_BATCH_CORRECT_LOCATION); if (placeId != null) { parameters.put("place_id", placeId); } if (woeId != null) { parameters.put("woe_id", woeId); } parameters.put("lat", Float.toString(location.getLatitude())); parameters.put("lon", Float.toString(location.getLongitude())); parameters.put("accuracy", Integer.toString(location.getAccuracy())); // Note: This method requires an HTTP POST request. Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); // This method has no specific response - It returns an empty sucess response // if it completes without error. if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * * @param photoId * Photo id (required). * @param placeId * A Flickr Places ID. (While optional, you must pass either a valid Places ID or a WOE ID.) * @param woeId * A Where On Earth (WOE) ID. (While optional, you must pass either a valid Places ID or a WOE ID.) * @throws FlickrException */ public void correctLocation(String photoId, String placeId, String woeId) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_CORRECT_LOCATION); parameters.put("photo_id", photoId); if (placeId != null) { parameters.put("place_id", placeId); } if (woeId != null) { parameters.put("woe_id", woeId); } // Note: This method requires an HTTP POST request. Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); // This method has no specific response - It returns an empty sucess response // if it completes without error. if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } /** * Return a list of photos for a user at a specific latitude, longitude and accuracy. * * @param location * @param extras * @param perPage * @param page * @return The collection of Photo objects * @throws FlickrException * @see com.flickr4java.flickr.photos.Extras */ public PhotoList<Photo> photosForLocation(GeoData location, Set<String> extras, int perPage, int page) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); PhotoList<Photo> photos = new PhotoList<Photo>(); parameters.put("method", METHOD_PHOTOS_FOR_LOCATION); 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)); } parameters.put("lat", Float.toString(location.getLatitude())); parameters.put("lon", Float.toString(location.getLongitude())); parameters.put("accuracy", Integer.toString(location.getAccuracy())); 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; } /** * Indicate the state of a photo's geotagginess beyond latitude and longitude. * <p> * * Note : photos passed to this method must already be geotagged (using the {@link GeoInterface#setLocation(String, GeoData)} method). * * @param photoId * Photo id (required). * @param context * Context is a numeric value representing the photo's geotagginess beyond latitude and longitude. For example, you may wish to indicate that a * photo was taken "indoors" (1) or "outdoors" (2). * @throws FlickrException */ public void setContext(String photoId, int context) throws FlickrException { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("method", METHOD_SET_CONTEXT); parameters.put("photo_id", photoId); parameters.put("context", "" + context); // Note: This method requires an HTTP POST request. Response response = transport.post(transport.getPath(), parameters, apiKey, sharedSecret); // This method has no specific response - It returns an empty sucess response // if it completes without error. if (response.isError()) { throw new FlickrException(response.getErrorCode(), response.getErrorMessage()); } } }