Java tutorial
/** * Copyright (C) 2011 by Sachin Handiekar * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.jinstagram; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonSyntaxException; import org.apache.commons.lang3.StringUtils; import org.jinstagram.auth.model.OAuthConstants; import org.jinstagram.auth.model.OAuthRequest; import org.jinstagram.auth.model.Token; import org.jinstagram.entity.comments.MediaCommentResponse; import org.jinstagram.entity.comments.MediaCommentsFeed; import org.jinstagram.entity.common.Pagination; import org.jinstagram.entity.likes.LikesFeed; import org.jinstagram.entity.locations.LocationInfo; import org.jinstagram.entity.locations.LocationSearchFeed; import org.jinstagram.entity.media.MediaInfoFeed; import org.jinstagram.entity.relationships.RelationshipFeed; import org.jinstagram.entity.tags.TagInfoFeed; import org.jinstagram.entity.tags.TagMediaFeed; import org.jinstagram.entity.tags.TagSearchFeed; import org.jinstagram.entity.users.basicinfo.UserInfo; import org.jinstagram.entity.users.feed.MediaFeed; import org.jinstagram.entity.users.feed.UserFeed; import org.jinstagram.exceptions.InstagramException; import org.jinstagram.exceptions.InstagramServiceException; import org.jinstagram.http.Response; import org.jinstagram.http.Verbs; import org.jinstagram.model.Constants; import org.jinstagram.model.Methods; import org.jinstagram.model.QueryParam; import org.jinstagram.model.Relationship; import org.jinstagram.utils.Preconditions; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * Instagram * * @author Sachin Handiekar * @version 1.0 */ public class Instagram { private Token accessToken; private final String clientId; public Instagram(Token accessToken) { this.accessToken = accessToken; clientId = null; } /** * Create a new Instagram instance only appropriate for unauthenticated requests (i.e. on behalf of the * application but not any particular user) */ public Instagram(String clientId) { this.accessToken = null; this.clientId = clientId; } /** * @return the accessToken */ public Token getAccessToken() { return accessToken; } /** * @param accessToken the accessToken to set */ public void setAccessToken(Token accessToken) { this.accessToken = accessToken; } /** * Get basic information about a user. * * @param userId user-id * @return a MediaFeed object. * @throws InstagramException if any error occurs. */ public UserInfo getUserInfo(long userId) throws InstagramException { Preconditions.checkNotNull(userId, "UserId cannot be null."); String apiMethod = String.format(Methods.USERS_WITH_ID, userId); UserInfo userInfo = this.createInstagramObject(Verbs.GET, UserInfo.class, apiMethod, null); return userInfo; } /** * Get basic information about a user. * * @param userId user-id * @return a MediaFeed object. * @throws InstagramException if any error occurs. */ public UserInfo getCurrentUserInfo() throws InstagramException { UserInfo userInfo = this.createInstagramObject(Verbs.GET, UserInfo.class, Methods.USERS_SELF, null); return userInfo; } /** * See the authenticated user's feed. * * @return a MediaFeed object. * @throws InstagramException if any error occurs. */ public MediaFeed getUserFeeds() throws InstagramException { MediaFeed userFeed = this.createInstagramObject(Verbs.GET, MediaFeed.class, Methods.USERS_SELF_FEED, null); return userFeed; } /** * Get the most recent media published by a user. * * @param userId userId of the User. * @return a MediaFeed object. * @throws InstagramException if any error occurs */ public MediaFeed getRecentMediaFeed(long userId) throws InstagramException { Preconditions.checkNotNull(userId, "UserId cannot be null."); String methodName = String.format(Methods.USERS_RECENT_MEDIA, userId); MediaFeed recentMediaFeed = this.createInstagramObject(Verbs.GET, MediaFeed.class, methodName, null); return recentMediaFeed; } /** * Get the authenticated user's list of media they've liked. * * @return a MediaFeed object. * @throws InstagramException if any error occurs. */ public MediaFeed getUserLikedMediaFeed() throws InstagramException { MediaFeed userLikedMedia = this.createInstagramObject(Verbs.GET, MediaFeed.class, Methods.USERS_SELF_LIKED_MEDIA, null); return userLikedMedia; } /** * Search for a user by name. * * @param query A query string. * @return a UserFeed object. * @throws InstagramException if any error occurs. */ public UserFeed searchUser(String query) throws InstagramException { Preconditions.checkNotNull(query, "search query cannot be null."); Map<String, String> params = new HashMap<String, String>(); params.put(QueryParam.SEARCH_QUERY, query); UserFeed userFeed = this.createInstagramObject(Verbs.GET, UserFeed.class, Methods.USERS_SEARCH, params); return userFeed; } /** * Get the list of users this user follows. * * @param userId userId of the User. * @return a UserFeed object. * @throws InstagramException if any error occurs. */ public UserFeed getUserFollowList(long userId) throws InstagramException { Preconditions.checkNotNull(userId, "userId cannot be null."); String apiMethod = String.format(Methods.USERS_ID_FOLLOWS, userId); UserFeed userFeed = this.createInstagramObject(Verbs.GET, UserFeed.class, apiMethod, null); return userFeed; } /** * Get the list of users this user is followed by. * * @param userId userId of the User. * @return a UserFeed object. * @throws InstagramException if any error occurs. */ public UserFeed getUserFollowedByList(long userId) throws InstagramException { Preconditions.checkNotNull(userId, "userId cannot be null."); String apiMethod = String.format(Methods.USERS_ID_FOLLOWED_BY, userId); UserFeed userFeed = this.createInstagramObject(Verbs.GET, UserFeed.class, apiMethod, null); return userFeed; } /** * Get a list of users who have requested this user's permission to follow * * @return a UserFeed object. * @throws InstagramException if any error occurs. */ public UserFeed getUserRequestedBy() throws InstagramException { UserFeed userFeed = this.createInstagramObject(Verbs.GET, UserFeed.class, Methods.USERS_SELF_REQUESTED_BY, null); return userFeed; } /** * Get information about the current user's relationship * (follow/following/etc) to another user. * * @param userId userId of the User. * @return a Relationship feed object. * @throws InstagramException if any error occurs. */ public RelationshipFeed getUserRelationship(long userId) throws InstagramException { Preconditions.checkNotNull(userId, "userId cannot be null."); String apiMethod = String.format(Methods.USERS_ID_RELATIONSHIP, userId); RelationshipFeed feed = this.createInstagramObject(Verbs.GET, RelationshipFeed.class, apiMethod, null); return feed; } /** * Set the relationship between the current user and the target user * * @param userId userId of the user. * @param relationship Relationship status * @return a Relationship feed object * @throws InstagramException if any error occurs. */ public RelationshipFeed setUserRelationship(long userId, Relationship relationship) throws InstagramException { Preconditions.checkNotNull(userId, "userId cannot be null."); Preconditions.checkNotNull(relationship, "relationship cannot be null."); String apiMethod = String.format(Methods.USERS_ID_RELATIONSHIP, userId); Map<String, String> params = new HashMap<String, String>(); params.put(QueryParam.ACTION, relationship.toString()); RelationshipFeed feed = this.createInstagramObject(Verbs.POST, RelationshipFeed.class, apiMethod, params); return feed; } /** * Get information about a media object. * * @param mediaId mediaId of the Media object. * @return a mediaFeed object. * @throws InstagramException if any error occurs. */ public MediaInfoFeed getMediaInfo(long mediaId) throws InstagramException { Preconditions.checkNotNull(mediaId, "mediaId cannot be null."); String apiMethod = String.format(Methods.MEDIA_BY_ID, mediaId); MediaInfoFeed feed = this.createInstagramObject(Verbs.GET, MediaInfoFeed.class, apiMethod, null); return feed; } /** * Search for media in a given area. * * @param latitude Latitude of the center search coordinate. * @param longitude Longitude of the center search coordinate. * @return a MediaFeed object. * @throws InstagramException if any error occurs */ public MediaFeed searchMedia(double latitude, double longitude) throws InstagramException { Map<String, String> params = new HashMap<String, String>(); params.put(QueryParam.LATITUDE, Double.toString(latitude)); params.put(QueryParam.LONGITUDE, Double.toString(longitude)); MediaFeed mediaFeed = createInstagramObject(Verbs.GET, MediaFeed.class, Methods.MEDIA_SEARCH, params); return mediaFeed; } /** * Get a list of what media is most popular at the moment. * * @return a MediaFeed object. * @throws InstagramException if any error occurs. */ public MediaFeed getPopularMedia() throws InstagramException { MediaFeed mediaFeed = createInstagramObject(Verbs.GET, MediaFeed.class, Methods.MEDIA_POPULAR, null); return mediaFeed; } /** * Get a full list of comments on a media. * * @param mediaId a mediaId * @return a MediaCommentsFeed object. * @throws InstagramException if any error occurs. */ public MediaCommentsFeed getMediaComments(long mediaId) throws InstagramException { String apiMethod = String.format(Methods.MEDIA_COMMENTS, mediaId); MediaCommentsFeed feed = createInstagramObject(Verbs.GET, MediaCommentsFeed.class, apiMethod, null); return feed; } /** * Create a comment on a media. * * @param mediaId a mediaId * @param text Text to post as a comment on the media as specified in * media-id. * @return a MediaCommentResponse feed. * @throws InstagramException if any error occurs. */ public MediaCommentResponse setMediaComments(long mediaId, String text) throws InstagramException { Map<String, String> params = new HashMap<String, String>(); params.put(QueryParam.TEXT, text); String apiMethod = String.format(Methods.MEDIA_COMMENTS, mediaId); MediaCommentResponse feed = createInstagramObject(Verbs.POST, MediaCommentResponse.class, apiMethod, params); return feed; } /** * Remove a comment either on the authenticated user's media or authored by * the authenticated user. * * @param mediaId a mediaId of the Media * @param commentId a commentId of the Comment * @return a MediaCommentResponse feed. * @throws InstagramException if any error occurs. */ public MediaCommentResponse deleteMediaCommentById(long mediaId, long commentId) throws InstagramException { String apiMethod = String.format(Methods.DELETE_MEDIA_COMMENTS, mediaId, commentId); MediaCommentResponse feed = createInstagramObject(Verbs.DELETE, MediaCommentResponse.class, apiMethod, null); return feed; } /** * Get a list of users who have liked this media. * * @param mediaId a mediaId of the Media * @return a LikesFeed object. * @throws InstagramException if any error occurs. */ public LikesFeed getUserLikes(long mediaId) throws InstagramException { String apiMethod = String.format(Methods.LIKES_BY_MEDIA_ID, mediaId); LikesFeed feed = createInstagramObject(Verbs.GET, LikesFeed.class, apiMethod, null); return feed; } /** * Set a like on this media by the currently authenticated user. * * @param mediaId a mediaId of the Media * @return a LikesFeed object. * @throws InstagramException if any error occurs. */ public LikesFeed setUserLike(long mediaId) throws InstagramException { String apiMethod = String.format(Methods.LIKES_BY_MEDIA_ID, mediaId); LikesFeed feed = createInstagramObject(Verbs.POST, LikesFeed.class, apiMethod, null); return feed; } /** * Remove a like on this media by the currently authenticated user. * * @param mediaId a mediaId of the Media * @return a LikesFeed object. * @throws InstagramException if any error occurs. */ public LikesFeed deleteUserLike(long mediaId) throws InstagramException { String apiMethod = String.format(Methods.LIKES_BY_MEDIA_ID, mediaId); LikesFeed feed = createInstagramObject(Verbs.DELETE, LikesFeed.class, apiMethod, null); return feed; } /** * Get information about a tag object. * * @param tagName name of the tag. * @return a TagInfoFeed object. * @throws InstagramException if any error occurs. */ public TagInfoFeed getTagInfo(String tagName) throws InstagramException { String apiMethod = String.format(Methods.TAGS_BY_NAME, tagName); TagInfoFeed feed = createInstagramObject(Verbs.GET, TagInfoFeed.class, apiMethod, null); return feed; } /** * Get a list of recently tagged media. * * @param tagName name of the tag. * @return a TagMediaFeed object. * @throws InstagramException if any error occurs. */ public TagMediaFeed getRecentMediaTags(String tagName) throws InstagramException { String apiMethod = String.format(Methods.TAGS_RECENT_MEDIA, tagName); TagMediaFeed feed = createInstagramObject(Verbs.GET, TagMediaFeed.class, apiMethod, null); return feed; } /** * Search for tags by name - results are ordered first as an exact match, * then by popularity. * * @param tagName name of the tag * @return a TagSearchFeed object. * @throws InstagramException if any error occurs. */ public TagSearchFeed searchTags(String tagName) throws InstagramException { Map<String, String> params = new HashMap<String, String>(); params.put(QueryParam.SEARCH_QUERY, tagName); TagSearchFeed feed = createInstagramObject(Verbs.GET, TagSearchFeed.class, Methods.TAGS_SEARCH, params); return feed; } /** * Get information about a location. * * @param locationId an id of the Location * @return a LocationInfo object. * @throws InstagramException if any error occurs. */ public LocationInfo getLocationInfo(long locationId) throws InstagramException { String apiMethod = String.format(Methods.LOCATIONS_BY_ID, locationId); LocationInfo feed = createInstagramObject(Verbs.GET, LocationInfo.class, apiMethod, null); return feed; } /** * Get a list of recent media objects from a given location. * * @param locationId id of the location * @return a MediaFeed object. * @throws InstagramException if any error occurs. */ public MediaFeed getRecentMediaByLocation(long locationId) throws InstagramException { return getRecentMediaByLocation(locationId, null, null, null); } /** * Get a list of recent media objects from a given location. * * @param locationId id of the location * @param minTimestamp Media returned will be after this UNIX timestamp * @param maxTimestamp Media returned will be before this UNIX timestamp * @return a MediaFeed object. * @throws InstagramException if any error occurs. */ public MediaFeed getRecentMediaByLocation(long locationId, Long minTimestamp, Long maxTimestamp) throws InstagramException { return getRecentMediaByLocation(locationId, null, minTimestamp, maxTimestamp); } /** * Get a list of recent media objects from a given location. * * @param locationId id of the location * @param minTimestamp Media returned will be after this UNIX timestamp * @param maxTimestamp Media returned will be before this UNIX timestamp * @param count Media count to be returned in request * @return a MediaFeed object. * @throws InstagramException if any error occurs. */ public MediaFeed getRecentMediaByLocation(long locationId, Integer count, Long minTimestamp, Long maxTimestamp) throws InstagramException { Map<String, String> params = new HashMap<String, String>(); if (minTimestamp != null) { params.put(QueryParam.MIN_TIMESTAMP, minTimestamp.toString()); } if (maxTimestamp != null) { params.put(QueryParam.MAX_TIMESTAMP, maxTimestamp.toString()); } if (maxTimestamp != null) { params.put(QueryParam.COUNT, count.toString()); } String apiMethod = String.format(Methods.LOCATIONS_RECENT_MEDIA_BY_ID, locationId); MediaFeed feed = createInstagramObject(Verbs.GET, MediaFeed.class, apiMethod, params); return feed; } /** * Get the next page of recent media objects from a previously executed request * @param pagination * @throws InstagramException */ public MediaFeed getRecentMediaNextPage(Pagination pagination) throws InstagramException { return createInstagramObject(Verbs.GET, MediaFeed.class, StringUtils.removeStart(pagination.getNextUrl(), Constants.API_URL), null); } /** * Search for a location by geographic coordinate. * * @param latitude Latitude of the center search coordinate. * @param longitude Longitude of the center search coordinate. * @return a LocationSearchFeed object. * @throws InstagramException if any error occurs. */ public LocationSearchFeed searchLocation(double latitude, double longitude) throws InstagramException { Map<String, String> params = new HashMap<String, String>(); params.put(QueryParam.LATITUDE, Double.toString(latitude)); params.put(QueryParam.LONGITUDE, Double.toString(longitude)); LocationSearchFeed feed = createInstagramObject(Verbs.GET, LocationSearchFeed.class, Methods.LOCATIONS_SEARCH, params); return feed; } /** * Search for a location by v2 Foursquare id. * * @param foursquareId Foursquare Venue ID of the location * @return a LocationSearchFeed object. * @throws InstagramException if any error occurs. */ public LocationSearchFeed searchFoursquareVenue(String foursquareId) throws InstagramException { Map<String, String> params = new HashMap<String, String>(); params.put(QueryParam.FOURSQUARE_V2_ID, foursquareId); LocationSearchFeed feed = createInstagramObject(Verbs.GET, LocationSearchFeed.class, Methods.LOCATIONS_SEARCH, params); return feed; } /** * Create a instagram object based on class-name and response. * * @param verbs * @param clazz * @param methodName * @param params * @return */ private <T> T createInstagramObject(Verbs verbs, Class<T> clazz, String methodName, Map<String, String> params) throws InstagramException { Response response; try { response = getApiResponse(verbs, methodName, params); } catch (IOException e) { throw new InstagramException("IOException while retrieving data", e); } if (response.getCode() >= 200 && response.getCode() < 300) { T object = createObjectFromResponse(clazz, response.getBody()); return object; } throw handleInstagramError(response); } private InstagramException handleInstagramError(Response response) throws InstagramException { if (response.getCode() == 400) { Gson gson = new Gson(); final InstagramErrorResponse error; try { JsonElement json = gson.fromJson(response.getBody(), JsonElement.class); if (json != null && json.isJsonObject() && json.getAsJsonObject().has("meta")) { error = gson.fromJson(json.getAsJsonObject().get("meta"), InstagramErrorResponse.class); } else { error = gson.fromJson(response.getBody(), InstagramErrorResponse.class); } } catch (JsonSyntaxException e) { throw new InstagramServiceException("Failed to decode error response " + response.getBody(), e, response.getCode()); } error.throwException(); } throw new InstagramServiceException( "Unknown error response code: " + response.getCode() + " " + response.getBody(), response.getCode()); } /** * Get response from Instagram. * * @param verb HTTP Verb * @param methodName Instagram API Method * @param params parameters which would be sent with the request. * @return Response object. */ private Response getApiResponse(Verbs verb, String methodName, Map<String, String> params) throws IOException { Response response = null; String apiResourceUrl = Constants.API_URL + methodName; OAuthRequest request = new OAuthRequest(verb, apiResourceUrl); // Additional parameters in url if (params != null) { for (Map.Entry<String, String> entry : params.entrySet()) { if (verb == Verbs.GET) { request.addQuerystringParameter(entry.getKey(), entry.getValue()); } else { request.addBodyParameter(entry.getKey(), entry.getValue()); } } } // Add the AccessToken to the Request Url if ((verb == Verbs.GET) || (verb == Verbs.DELETE)) { if (accessToken == null) { request.addQuerystringParameter(OAuthConstants.CLIENT_ID, clientId); } else { request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken.getToken()); } } else { if (accessToken == null) { request.addBodyParameter(OAuthConstants.CLIENT_ID, clientId); } else { request.addBodyParameter(OAuthConstants.ACCESS_TOKEN, accessToken.getToken()); } } response = request.send(); return response; } /** * Creates an object from the JSON response and the class which the object would be mapped to. * * @param clazz a class instance * @param response a JSON feed * @return a object of type <T> * @throws InstagramException if any error occurs. */ private <T> T createObjectFromResponse(Class<T> clazz, final String response) throws InstagramException { Gson gson = new Gson(); T object = null; try { object = clazz.newInstance(); object = gson.fromJson(response, clazz); } catch (InstantiationException e) { throw new InstagramException("Problem in Instantiation of type " + clazz.getName(), e); } catch (IllegalAccessException e) { throw new InstagramException("Couldn't create object of type " + clazz.getName(), e); } catch (Exception e) { throw new InstagramException("Error parsing json to object type " + clazz.getName(), e); } return object; } }