FileDocCategorySizeDatePackage
FacebookRestClient.javaAPI DocFacebook API47077Mon Jul 16 13:08:38 BST 2007com.facebook.api

FacebookRestClient

public class FacebookRestClient extends Object

Fields Summary
public static final String
TARGET_API_VERSION
public static final String
ERROR_TAG
public static final String
FB_SERVER
public static final String
SERVER_ADDR
public static final String
HTTPS_SERVER_ADDR
public static URL
SERVER_URL
public static URL
HTTPS_SERVER_URL
private final String
_secret
private final String
_apiKey
private final URL
_serverUrl
private String
_sessionKey
private boolean
_isDesktop
private String
_sessionSecret
private int
_userId
public static int
NUM_AUTOAPPENDED_PARAMS
private static boolean
DEBUG
private Boolean
_debug
private File
_uploadFile
protected static final String
CRLF
protected static final String
PREF
protected static final int
UPLOAD_BUFFER_SIZE
Constructors Summary
public FacebookRestClient(String apiKey, String secret)

    this(SERVER_URL, apiKey, secret, null);
  
public FacebookRestClient(String apiKey, String secret, String sessionKey)

    this(SERVER_URL, apiKey, secret, sessionKey);
  
public FacebookRestClient(String serverAddr, String apiKey, String secret, String sessionKey)

    this(new URL(serverAddr), apiKey, secret, sessionKey);
  
public FacebookRestClient(URL serverUrl, String apiKey, String secret, String sessionKey)

    _sessionKey = sessionKey;
    _apiKey = apiKey;
    _secret = secret;
    _serverUrl = (null != serverUrl) ? serverUrl : SERVER_URL;
  
Methods Summary
public java.lang.Stringauth_createToken()
Call this function and store the result, using it to generate the appropriate login url and then to retrieve the session information.

return
String the auth_token string

    Document d = this.callMethod(FacebookMethod.AUTH_CREATE_TOKEN);
    return d.getFirstChild().getTextContent();
  
public java.lang.Stringauth_getSession(java.lang.String authToken)
Call this function to retrieve the session information after your user has logged in.

param
authToken the token returned by auth_createToken or passed back to your callback_url.

	if (null != this._sessionKey) {
      return this._sessionKey;
	}
    Document d =
      this.callMethod(FacebookMethod.AUTH_GET_SESSION, new Pair<String, CharSequence>("auth_token",
                                                                                      authToken.toString()));
    this._sessionKey =
        d.getElementsByTagName("session_key").item(0).getFirstChild().getTextContent();
    this._userId =
        Integer.parseInt(d.getElementsByTagName("uid").item(0).getFirstChild().getTextContent());
    if (this._isDesktop)
      this._sessionSecret =
          d.getElementsByTagName("secret").item(0).getFirstChild().getTextContent();
    return this._sessionKey;
  
public intauth_getUserId(java.lang.String authToken)
Call this function to get the user ID.

return
The ID of the current session's user, or -1 if none.

	/*
	 * Get the session information if we don't have it; this will populate
	 * the user ID as well.
	 */
	if (null == this._sessionKey)
	  auth_getSession(authToken);
	return this._userId;
  
protected org.w3c.dom.DocumentcallMethod(com.facebook.api.FacebookMethod method, com.facebook.api.FacebookRestClient$Pair paramPairs)
Call the specified method, with the given parameters, and return a DOM tree with the results.

param
method the fieldName of the method
param
paramPairs a list of arguments to the method
throws
Exception with a description of any errors given to us by the server.

    return callMethod(method, Arrays.asList(paramPairs));
  
protected org.w3c.dom.DocumentcallMethod(com.facebook.api.FacebookMethod method, java.util.Collection paramPairs)
Call the specified method, with the given parameters, and return a DOM tree with the results.

param
method the fieldName of the method
param
paramPairs a list of arguments to the method
throws
Exception with a description of any errors given to us by the server.

    HashMap<String, CharSequence> params =
      new HashMap<String, CharSequence>(2 * method.numTotalParams());

    params.put("method", method.methodName());
    params.put("api_key", _apiKey);
    params.put("v", TARGET_API_VERSION);
    if (method.requiresSession()) {
      params.put("call_id", Long.toString(System.currentTimeMillis()));
      params.put("session_key", _sessionKey);
    }
    CharSequence oldVal;
    for (Pair<String, CharSequence> p: paramPairs) {
      oldVal = params.put(p.first, p.second);
      if (oldVal != null)
        System.err.printf("For parameter %s, overwrote old value %s with new value %s.", p.first,
                          oldVal, p.second);
    }

    assert (!params.containsKey("sig"));
    String signature = generateSignature(FacebookSignatureUtil.convert(params.entrySet()), method.requiresSession());
    params.put("sig", signature);

    try {
      DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
      boolean doHttps = this.isDesktop() && FacebookMethod.AUTH_GET_SESSION.equals(method);
      InputStream data =
        method.takesFile() ? postFileRequest(method.methodName(), params) : postRequest(method.methodName(),
                                                                                        params,
                                                                                        doHttps,
                                                                                        true);
      Document doc = builder.parse(data);
      doc.normalizeDocument();
      stripEmptyTextNodes(doc);

      if (isDebug())
        FacebookRestClient.printDom(doc, method.methodName() + "| "); // TEST
      NodeList errors = doc.getElementsByTagName(ERROR_TAG);
      if (errors.getLength() > 0) {
        int errorCode =
          Integer.parseInt(errors.item(0).getFirstChild().getFirstChild().getTextContent());
        String message = errors.item(0).getFirstChild().getNextSibling().getTextContent();
        throw new FacebookException(errorCode, message);
      }
      return doc;
    }
    catch (javax.xml.parsers.ParserConfigurationException ex) {
      System.err.println("huh?" + ex);
    }
    catch (org.xml.sax.SAXException ex) {
      throw new IOException("error parsing xml");
    }
    return null;
  
private static java.lang.CharSequencedelimit(java.util.Collection iterable)

    // could add a thread-safe version that uses StringBuffer as well
    if (iterable == null || iterable.isEmpty())
      return null;

    StringBuilder buffer = new StringBuilder();
    boolean notFirst = false;
    for (Object item: iterable) {
      if (notFirst)
        buffer.append(",");
      else
        notFirst = true;
      buffer.append(item.toString());
    }
    return buffer;
  
protected static java.lang.CharSequencedelimit(java.util.Collection entries, java.lang.CharSequence delimiter, java.lang.CharSequence equals, boolean doEncode)

    if (entries == null || entries.isEmpty())
      return null;

    StringBuilder buffer = new StringBuilder();
    boolean notFirst = false;
    for (Map.Entry<String, CharSequence> entry: entries) {
      if (notFirst)
        buffer.append(delimiter);
      else
        notFirst = true;
      CharSequence value = entry.getValue();
      buffer.append(entry.getKey()).append(equals).append(doEncode ? encode(value) : value);
    }
    return buffer;
  
private static java.lang.Stringencode(java.lang.CharSequence target)

    String result = target.toString();
    try {
      result = URLEncoder.encode(result, "UTF8");
    }
    catch (UnsupportedEncodingException e) {
      System.err.printf("Unsuccessful attempt to encode '%s' into UTF8", result);
    }
    return result;
  
public org.w3c.dom.Documentevents_get(java.lang.Integer userId, java.util.Collection eventIds, java.lang.Long startTime, java.lang.Long endTime)
Returns all visible events according to the filters specified. This may be used to find all events of a user, or to query specific eids.

param
eventIds filter by these event ID's (optional)
param
userId filter by this user only (optional)
param
startTime UTC lower bound (optional)
param
endTime UTC upper bound (optional)
return
Document of events

    ArrayList<Pair<String, CharSequence>> params =
      new ArrayList<Pair<String, CharSequence>>(FacebookMethod.EVENTS_GET.numParams());

    boolean hasUserId = null != userId && 0 != userId;
    boolean hasEventIds = null != eventIds && !eventIds.isEmpty();
    boolean hasStart = null != startTime && 0 != startTime;
    boolean hasEnd = null != endTime && 0 != endTime;

    if (hasUserId)
      params.add(new Pair<String, CharSequence>("uid", Integer.toString(userId)));
    if (hasEventIds)
      params.add(new Pair<String, CharSequence>("eids", delimit(eventIds)));
    if (hasStart)
      params.add(new Pair<String, CharSequence>("start_time", startTime.toString()));
    if (hasEnd)
      params.add(new Pair<String, CharSequence>("end_time", endTime.toString()));
    return this.callMethod(FacebookMethod.EVENTS_GET, params);
  
public org.w3c.dom.Documentevents_getMembers(java.lang.Number eventId)
Retrieves the membership list of an event

param
eventId event id
return
Document consisting of four membership lists corresponding to RSVP status, with keys 'attending', 'unsure', 'declined', and 'not_replied'

    assert (null != eventId);
    return this.callMethod(FacebookMethod.EVENTS_GET_MEMBERS,
                           new Pair<String, CharSequence>("eid", eventId.toString()));
  
protected static booleanextractBoolean(org.w3c.dom.Document doc)

    String content = doc.getFirstChild().getTextContent();
    return 1 == Integer.parseInt(content);    
  
public booleanfbml_refreshImgSrc(java.lang.String imageUrl)
Recaches the image with the specified imageUrl.

param
imageUrl String representing the image URL to refresh
return
boolean indicating whether the refresh succeeded

    return fbml_refreshImgSrc(new URL(imageUrl));
  
public booleanfbml_refreshImgSrc(java.net.URL imageUrl)
Recaches the image with the specified imageUrl.

param
imageUrl the image URL to refresh
return
boolean indicating whether the refresh succeeded

    return extractBoolean(this.callMethod(FacebookMethod.FBML_REFRESH_IMG_SRC,
                          new Pair<String, CharSequence>("url", imageUrl.toString())));
  
public booleanfbml_refreshRefUrl(java.lang.String url)
Recaches the referenced url.

param
url string representing the URL to refresh
return
boolean indicating whether the refresh succeeded

    return fbml_refreshRefUrl(new URL(url));
  
public booleanfbml_refreshRefUrl(java.net.URL url)
Recaches the referenced url.

param
url the URL to refresh
return
boolean indicating whether the refresh succeeded

    return extractBoolean(this.callMethod(FacebookMethod.FBML_REFRESH_REF_URL,
                                          new Pair<String, CharSequence>("url", url.toString())));
  
protected org.w3c.dom.DocumentfeedHandler(com.facebook.api.FacebookMethod feedMethod, java.lang.CharSequence title, java.lang.CharSequence body, java.util.Collection images, java.lang.Integer priority)

    assert (images == null || images.size() <= 4);

    ArrayList<Pair<String, CharSequence>> params =
      new ArrayList<Pair<String, CharSequence>>(feedMethod.numParams());

    params.add(new Pair<String, CharSequence>("title", title));
    if (null != body)
      params.add(new Pair<String, CharSequence>("body", body));
    if (null != priority)
      params.add(new Pair<String, CharSequence>("priority", priority.toString()));
    if (null != images && !images.isEmpty()) {
      int image_count = 0;
      for (Pair<URL, URL> image: images) {
        ++image_count;
        assert (image.first != null);
        params.add(new Pair<String, CharSequence>(String.format("image_%d", image_count),
                                                  image.first.toString()));
        if (image.second != null)
          params.add(new Pair<String, CharSequence>(String.format("image_%d_link", image_count),
                                                    image.second.toString()));
      }
    }
    return this.callMethod(feedMethod, params);
  
public org.w3c.dom.Documentfeed_publishActionOfUser(java.lang.CharSequence title, java.lang.CharSequence body, java.util.Collection images, java.lang.Integer priority)
Publish the notification of an action taken by a user to newsfeed.

param
title the title of the feed story
param
body the body of the feed story
param
images (optional) up to four pairs of image URLs and (possibly null) link URLs
param
priority
return

    return feedHandler(FacebookMethod.FEED_PUBLISH_ACTION_OF_USER, title, body, images, priority);
  
public org.w3c.dom.Documentfeed_publishActionOfUser(java.lang.CharSequence title, java.lang.CharSequence body)

see
FacebookRestClient#feed_publishActionOfUser(CharSequence,CharSequence,Collection,Integer)

    return feed_publishActionOfUser(title, body, null, null);
  
public org.w3c.dom.Documentfeed_publishActionOfUser(java.lang.CharSequence title, java.lang.CharSequence body, java.lang.Integer priority)

see
FacebookRestClient#feed_publishActionOfUser(CharSequence,CharSequence,Collection,Integer)

    return feed_publishActionOfUser(title, body, null, priority);
  
public org.w3c.dom.Documentfeed_publishActionOfUser(java.lang.CharSequence title, java.lang.CharSequence body, java.util.Collection images)

see
FacebookRestClient#feed_publishActionOfUser(CharSequence,CharSequence,Collection,Integer)

    return feed_publishActionOfUser(title, body, images, null);
  
public org.w3c.dom.Documentfeed_publishStoryToUser(java.lang.CharSequence title, java.lang.CharSequence body, java.util.Collection images, java.lang.Integer priority)
Publish a story to the logged-in user's newsfeed.

param
title the title of the feed story
param
body the body of the feed story
param
images (optional) up to four pairs of image URLs and (possibly null) link URLs
param
priority
return

    return feedHandler(FacebookMethod.FEED_PUBLISH_STORY_TO_USER, title, body, images, priority);
  
public org.w3c.dom.Documentfeed_publishStoryToUser(java.lang.CharSequence title, java.lang.CharSequence body)

see
FacebookRestClient#feed_publishStoryToUser(CharSequence,CharSequence,Collection,Integer)

    return feed_publishStoryToUser(title, body, null, null);
  
public org.w3c.dom.Documentfeed_publishStoryToUser(java.lang.CharSequence title, java.lang.CharSequence body, java.lang.Integer priority)

see
FacebookRestClient#feed_publishStoryToUser(CharSequence,CharSequence,Collection,Integer)

    return feed_publishStoryToUser(title, body, null, priority);
  
public org.w3c.dom.Documentfeed_publishStoryToUser(java.lang.CharSequence title, java.lang.CharSequence body, java.util.Collection images)

see
FacebookRestClient#feed_publishStoryToUser(CharSequence,CharSequence,Collection,Integer)

    return feed_publishStoryToUser(title, body, images, null);
  
public org.w3c.dom.Documentfql_query(java.lang.CharSequence query)
Retrieves the results of a Facebook Query Language query

param
query : the FQL query statement
return
varies depending on the FQL query

    assert (null != query);
    return this.callMethod(FacebookMethod.FQL_QUERY,
                           new Pair<String, CharSequence>("query", query));
  
public org.w3c.dom.Documentfriends_areFriends(int userId1, int userId2)
Retrieves the friends of the currently logged in user.

return
array of friends

    return this.callMethod(FacebookMethod.FRIENDS_ARE_FRIENDS,
                           new Pair<String, CharSequence>("uids1", Integer.toString(userId1)),
                           new Pair<String, CharSequence>("uids2", Integer.toString(userId2)));
  
public org.w3c.dom.Documentfriends_areFriends(java.util.Collection userIds1, java.util.Collection userIds2)

    assert (userIds1 != null && userIds2 != null);
    assert (!userIds1.isEmpty() && !userIds2.isEmpty());
    assert (userIds1.size() == userIds2.size());

    return this.callMethod(FacebookMethod.FRIENDS_ARE_FRIENDS,
                           new Pair<String, CharSequence>("uids1", delimit(userIds1)),
                           new Pair<String, CharSequence>("uids2", delimit(userIds2)));
  
public org.w3c.dom.Documentfriends_get()
Retrieves the friends of the currently logged in user.

return
array of friends

    return this.callMethod(FacebookMethod.FRIENDS_GET);
  
public org.w3c.dom.Documentfriends_getAppUsers()
Retrieves the friends of the currently logged in user, who are also users of the calling application.

return
array of friends

    return this.callMethod(FacebookMethod.FRIENDS_GET_APP_USERS);
  
private java.lang.StringgenerateSignature(java.util.List params, boolean requiresSession)

    String secret = (isDesktop() && requiresSession) ? this._sessionSecret : this._secret;
    return FacebookSignatureUtil.generateSignature(params, secret);
  
public org.w3c.dom.Documentgroups_get(java.lang.Integer userId, java.util.Collection groupIds)
Retrieves the groups associated with a user

param
userId Optional: User associated with groups. A null parameter will default to the session user.
param
groupIds Optional: group ids to query. A null parameter will get all groups for the user.
return
array of groups

    boolean hasGroups = (null != groupIds && !groupIds.isEmpty());
    if (null != userId)
      return hasGroups ?
             this.callMethod(FacebookMethod.GROUPS_GET, new Pair<String, CharSequence>("uid",
                                                                                       userId.toString()),
                             new Pair<String, CharSequence>("gids", delimit(groupIds))) :
             this.callMethod(FacebookMethod.GROUPS_GET,
                             new Pair<String, CharSequence>("uid", userId.toString()));
    else
      return hasGroups ?
             this.callMethod(FacebookMethod.GROUPS_GET, new Pair<String, CharSequence>("gids",
                                                                                       delimit(groupIds))) :
             this.callMethod(FacebookMethod.GROUPS_GET);
  
public org.w3c.dom.Documentgroups_getMembers(java.lang.Number groupId)
Retrieves the membership list of a group

param
groupId the group id
return
a Document containing four membership lists of 'members', 'admins', 'officers', and 'not_replied'

    assert (null != groupId);
    return this.callMethod(FacebookMethod.GROUPS_GET_MEMBERS,
                           new Pair<String, CharSequence>("gid", groupId.toString()));
  
public booleanisDebug()

    return (null == _debug) ? FacebookRestClient.DEBUG : _debug.booleanValue();
  
public booleanisDesktop()

    return this._isDesktop;
  
public org.w3c.dom.Documentnotifications_get()
Retrieves the outstanding notifications for the session user.

return
a Document containing notification count pairs for 'messages', 'pokes' and 'shares', a uid list of 'friend_requests', a gid list of 'group_invites', and an eid list of 'event_invites'

    return this.callMethod(FacebookMethod.NOTIFICATIONS_GET);
  
public java.net.URLnotifications_send(java.util.Collection recipientIds, java.lang.CharSequence notification, java.lang.CharSequence email)
Send a notification message to the specified users.

param
recipientIds the user ids to which the message is to be sent
param
notification the FBML to display on the notifications page
param
email the FBML to send to the specified users via email, or null if no email should be sent
return
a URL, possibly null, to which the user should be redirected to finalize the sending of the email

    assert (null != recipientIds && !recipientIds.isEmpty());
    assert (null != notification);
    ArrayList<Pair<String, CharSequence>> args = new ArrayList<Pair<String,CharSequence>>(3);
    args.add(new Pair<String, CharSequence>("to_ids", delimit(recipientIds)));
    args.add(new Pair<String, CharSequence>("notification", email));
    if (null != email)
      args.add(new Pair<String, CharSequence>("email", email));
    Document d = this.callMethod(FacebookMethod.NOTIFICATIONS_SEND, args);
    String url = d.getFirstChild().getTextContent();
    return (null == url || "".equals(url)) ? null : new URL(url);
  
public java.net.URLnotifications_sendRequest(java.util.Collection recipientIds, java.lang.CharSequence type, java.lang.CharSequence content, java.net.URL image, boolean isInvite)
Send a request or invitations to the specified users.

param
recipientIds the user ids to which the request is to be sent
param
type the type of request/invitation - e.g. the word "event" in "1 event invitation."
param
content Content of the request/invitation. This should be FBML containing only links and the special tag <fb:req-choice url="" label="" /> to specify the buttons to be included in the request.
param
image URL of an image to show beside the request. It will be resized to be 100 pixels wide.
param
isInvite whether this is a "request" or an "invite"
return
a URL, possibly null, to which the user should be redirected to finalize the sending of the message

    assert (null != recipientIds && !recipientIds.isEmpty());
    assert (null != type);
    assert (null != content);
    assert (null != image);

    Document d =
      this.callMethod(FacebookMethod.NOTIFICATIONS_SEND_REQUEST, 
                      new Pair<String, CharSequence>("to_ids", delimit(recipientIds)),
                      new Pair<String, CharSequence>("type", type),
                      new Pair<String, CharSequence>("content", content),
                      new Pair<String, CharSequence>("image", image.toString()),
                      new Pair<String, CharSequence>("invite", isInvite ? "1" : "0"));
    String url = d.getFirstChild().getTextContent();
    return (null == url || "".equals(url)) ? null : new URL(url);
  
public booleanphotos_addTag(java.lang.Long photoId, java.lang.Integer taggedUserId, java.lang.Double xPct, java.lang.Double yPct)
Adds a tag to a photo.

param
photoId The photo id of the photo to be tagged.
param
xPct The horizontal position of the tag, as a percentage from 0 to 100, from the left of the photo.
param
yPct The vertical position of the tag, as a percentage from 0 to 100, from the top of the photo.
param
taggedUserId The list of photos from which to extract photo tags.
return
whether the tag was successfully added.

    return photos_addTag(photoId, xPct, yPct, taggedUserId, null);
  
public booleanphotos_addTag(java.lang.Long photoId, java.lang.CharSequence tagText, java.lang.Double xPct, java.lang.Double yPct)
Adds a tag to a photo.

param
photoId The photo id of the photo to be tagged.
param
xPct The horizontal position of the tag, as a percentage from 0 to 100, from the left of the photo.
param
yPct The list of photos from which to extract photo tags.
param
tagText The text of the tag.
return
whether the tag was successfully added.

    return photos_addTag(photoId, xPct, yPct, null, tagText);
  
private booleanphotos_addTag(java.lang.Long photoId, java.lang.Double xPct, java.lang.Double yPct, java.lang.Integer taggedUserId, java.lang.CharSequence tagText)

    assert (null != photoId && !photoId.equals(0));
    assert (null != taggedUserId || null != tagText);
    assert (null != xPct && xPct >= 0 && xPct <= 100);
    assert (null != yPct && yPct >= 0 && yPct <= 100);
    Document d =
      this.callMethod(FacebookMethod.PHOTOS_ADD_TAG, new Pair<String, CharSequence>("pid",
                                                                                    photoId.toString()),
                      new Pair<String, CharSequence>("tag_uid", taggedUserId.toString()),
                      new Pair<String, CharSequence>("x", xPct.toString()),
                      new Pair<String, CharSequence>("y", yPct.toString()));
    return extractBoolean(d);
  
public org.w3c.dom.Documentphotos_addTags(java.lang.Long photoId, java.util.Collection tags)
Adds several tags to a photo.

param
photoId The photo id of the photo to be tagged.
param
tags A list of PhotoTags.
return
a list of booleans indicating whether the tag was successfully added.

    assert (photoId > 0);
    assert (null != tags && !tags.isEmpty());
    JSONWriter tagsJSON = new JSONStringer().array();
    for (PhotoTag tag: tags)
      tagsJSON = tag.jsonify(tagsJSON);
    String tagStr = tagsJSON.endArray().toString();

    return this.callMethod(FacebookMethod.PHOTOS_ADD_TAG,
                           new Pair<String, CharSequence>("pid", photoId.toString()),
                           new Pair<String, CharSequence>("tags", tagStr));
  
public org.w3c.dom.Documentphotos_createAlbum(java.lang.String albumName)
Creates an album.

param
albumName The list of photos from which to extract photo tags.
return
the created album

    return this.photos_createAlbum(albumName, null/*description*/, null/*location*/);
  
public org.w3c.dom.Documentphotos_createAlbum(java.lang.String name, java.lang.String description, java.lang.String location)
Creates an album.

param
name The album name.
param
location The album location (optional).
param
description The album description (optional).
return
an array of photo objects.

    assert (null != name && !"".equals(name));
    ArrayList<Pair<String, CharSequence>> params =
      new ArrayList<Pair<String, CharSequence>>(FacebookMethod.PHOTOS_CREATE_ALBUM.numParams());
    params.add(new Pair<String, CharSequence>("name", name));
    if (null != description)
      params.add(new Pair<String, CharSequence>("description", description));
    if (null != location)
      params.add(new Pair<String, CharSequence>("location", location));
    return this.callMethod(FacebookMethod.PHOTOS_CREATE_ALBUM, params);
  
public org.w3c.dom.Documentphotos_get(java.lang.Integer subjId, java.lang.Long albumId, java.util.Collection photoIds)
Used to retrieve photo objects using the search parameters (one or more of the parameters must be provided).

param
subjId retrieve from photos associated with this user (optional).
param
albumId retrieve from photos from this album (optional)
param
photoIds retrieve from this list of photos (optional)
return
an Document of photo objects.

    ArrayList<Pair<String, CharSequence>> params =
      new ArrayList<Pair<String, CharSequence>>(FacebookMethod.PHOTOS_GET.numParams());

    boolean hasUserId = null != subjId && 0 != subjId;
    boolean hasAlbumId = null != albumId && 0 != albumId;
    boolean hasPhotoIds = null != photoIds && !photoIds.isEmpty();
    assert (hasUserId || hasAlbumId || hasPhotoIds);

    if (hasUserId)
      params.add(new Pair<String, CharSequence>("subj_id", Integer.toString(subjId)));
    if (hasAlbumId)
      params.add(new Pair<String, CharSequence>("aid", Long.toString(albumId)));
    if (hasPhotoIds)
      params.add(new Pair<String, CharSequence>("pids", delimit(photoIds)));

    return this.callMethod(FacebookMethod.PHOTOS_GET, params);
  
public org.w3c.dom.Documentphotos_get(java.lang.Long albumId, java.util.Collection photoIds)

    return photos_get(null/*subjId*/, albumId, photoIds);
  
public org.w3c.dom.Documentphotos_get(java.lang.Integer subjId, java.util.Collection photoIds)

    return photos_get(subjId, null/*albumId*/, photoIds);
  
public org.w3c.dom.Documentphotos_get(java.lang.Integer subjId, java.lang.Long albumId)

    return photos_get(subjId, albumId, null/*photoIds*/);
  
public org.w3c.dom.Documentphotos_get(java.util.Collection photoIds)

    return photos_get(null/*subjId*/, null/*albumId*/, photoIds);
  
public org.w3c.dom.Documentphotos_get(java.lang.Long albumId)

    return photos_get(null/*subjId*/, albumId, null/*photoIds*/);
  
public org.w3c.dom.Documentphotos_get(java.lang.Integer subjId)

    return photos_get(subjId, null/*albumId*/, null/*photoIds*/);
  
public org.w3c.dom.Documentphotos_getAlbums(java.lang.Integer userId, java.util.Collection albumIds)
Retrieves album metadata. Pass a user id and/or a list of album ids to specify the albums to be retrieved (at least one must be provided)

param
userId retrieve metadata for albums created the id of the user whose album you wish (optional).
param
albumIds the ids of albums whose metadata is to be retrieved
return
album objects.

    boolean hasUserId = null != userId && userId != 0;
    boolean hasAlbumIds = null != albumIds && !albumIds.isEmpty();
    assert (hasUserId || hasAlbumIds); // one of the two must be provided

    if (hasUserId)
      return (hasAlbumIds) ?
             this.callMethod(FacebookMethod.PHOTOS_GET_ALBUMS, new Pair<String, CharSequence>("uid",
                                                                                              Integer.toString(userId)),
                             new Pair<String, CharSequence>("aids", delimit(albumIds))) :
             this.callMethod(FacebookMethod.PHOTOS_GET_ALBUMS,
                             new Pair<String, CharSequence>("uid", Integer.toString(userId)));
    else
      return this.callMethod(FacebookMethod.PHOTOS_GET_ALBUMS,
                             new Pair<String, CharSequence>("aids", delimit(albumIds)));
  
public org.w3c.dom.Documentphotos_getAlbums(java.lang.Integer userId)

    return photos_getAlbums(userId, null /*albumIds*/);
  
public org.w3c.dom.Documentphotos_getAlbums(java.util.Collection albumIds)

    return photos_getAlbums(null /*userId*/, albumIds);
  
public org.w3c.dom.Documentphotos_getTags(java.util.Collection photoIds)
Retrieves the tags for the given set of photos.

param
photoIds The list of photos from which to extract photo tags.
return
the created album

    return this.callMethod(FacebookMethod.PHOTOS_GET_TAGS,
                           new Pair<String, CharSequence>("pids", delimit(photoIds)));
  
public org.w3c.dom.Documentphotos_upload(java.io.File photo)

    return /* caption */ /* albumId */photos_upload(photo, null, null);
  
public org.w3c.dom.Documentphotos_upload(java.io.File photo, java.lang.String caption)

    return /* albumId */photos_upload(photo, caption, null);
  
public org.w3c.dom.Documentphotos_upload(java.io.File photo, java.lang.Long albumId)

    return /* caption */photos_upload(photo, null, albumId);
  
public org.w3c.dom.Documentphotos_upload(java.io.File photo, java.lang.String caption, java.lang.Long albumId)

    ArrayList<Pair<String, CharSequence>> params =
      new ArrayList<Pair<String, CharSequence>>(FacebookMethod.PHOTOS_UPLOAD.numParams());
    assert (photo.exists() && photo.canRead());
    this._uploadFile = photo;
    if (null != albumId)
      params.add(new Pair<String, CharSequence>("aid", Long.toString(albumId)));
    if (null != caption)
      params.add(new Pair<String, CharSequence>("caption", caption));
    return callMethod(FacebookMethod.PHOTOS_UPLOAD, params);
  
public java.io.InputStreampostFileRequest(java.lang.String methodName, java.util.Map params)


     
                                          
    assert (null != _uploadFile);
    try {
      BufferedInputStream bufin = new BufferedInputStream(new FileInputStream(_uploadFile));

      String boundary = Long.toString(System.currentTimeMillis(), 16);
      URLConnection con = SERVER_URL.openConnection();
      con.setDoInput(true);
      con.setDoOutput(true);
      con.setUseCaches(false);
      con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
      con.setRequestProperty("MIME-version", "1.0");

      DataOutputStream out = new DataOutputStream(con.getOutputStream());

      for (Map.Entry<String, CharSequence> entry: params.entrySet()) {
        out.writeBytes(PREF + boundary + CRLF);
        out.writeBytes("Content-disposition: form-data; name=\"" + entry.getKey() + "\"");
        out.writeBytes(CRLF + CRLF);
        out.writeBytes(entry.getValue().toString());
        out.writeBytes(CRLF);
      }

      out.writeBytes(PREF + boundary + CRLF);
      out.writeBytes("Content-disposition: form-data; filename=\"" + _uploadFile.getName() + "\"" +
                     CRLF);
      out.writeBytes("Content-Type: image/jpeg" + CRLF);
      // out.writeBytes("Content-Transfer-Encoding: binary" + CRLF); // not necessary

      // Write the file
      out.writeBytes(CRLF);
      byte b[] = new byte[UPLOAD_BUFFER_SIZE];
      int byteCounter = 0;
      int i;
      while (-1 != (i = bufin.read(b))) {
        byteCounter += i;
        out.write(b, 0, i);
      }
      out.writeBytes(CRLF + PREF + boundary + PREF + CRLF);

      out.flush();
      out.close();

      InputStream is = con.getInputStream();
      return is;
    }
    catch (Exception e) {
      System.out.println("exception: " + e.getMessage());
      e.printStackTrace();
      return null;
    }
  
private java.io.InputStreampostRequest(java.lang.CharSequence method, java.util.Map params, boolean doHttps, boolean doEncode)

    CharSequence buffer = (null == params) ? "" : delimit(params.entrySet(), "&", "=", doEncode);
    URL serverUrl = (doHttps) ? HTTPS_SERVER_URL : _serverUrl;
    if (isDebug()) {
      System.out.print(method);
      System.out.print(" POST: ");
      System.out.print(serverUrl.toString());
      System.out.print("/");
      System.out.println(buffer);
      System.out.flush();
    }

    HttpURLConnection conn = (HttpURLConnection) serverUrl.openConnection();
    try {
      conn.setRequestMethod("POST");
    }
    catch (ProtocolException ex) {
      System.err.println("huh?" + ex);
    }
    conn.setDoOutput(true);
    conn.connect();
    conn.getOutputStream().write(buffer.toString().getBytes());

    return conn.getInputStream();
  
public static voidprintDom(org.w3c.dom.Node n, java.lang.String prefix)
Prints out the DOM tree.

    String outString = prefix;
    if (n.getNodeType() == Node.TEXT_NODE) {
      outString += "'" + n.getTextContent().trim() + "'";
    }
    else {
      outString += n.getNodeName();
    }
    System.out.println(outString);
    NodeList children = n.getChildNodes();
    int length = children.getLength();
    for (int i = 0; i < length; i++) {
      FacebookRestClient.printDom(children.item(i), prefix + "  ");
    }
  
public org.w3c.dom.Documentprofile_getFBML(java.lang.Integer userId)
Gets the FBML for a user's profile, including the content for both the profile box and the profile actions.

param
userId - the user whose profile FBML to set
return
a Document containing FBML markup

    return this.callMethod(FacebookMethod.PROFILE_GET_FBML,
                          new Pair<String, CharSequence>("uid", Integer.toString(userId)));

  
public booleanprofile_setFBML(java.lang.CharSequence fbmlMarkup, java.lang.Integer userId)
Sets the FBML for a user's profile, including the content for both the profile box and the profile actions.

param
userId - the user whose profile FBML to set
param
fbmlMarkup - refer to the FBML documentation for a description of the markup and its role in various contexts
return
a boolean indicating whether the FBML was successfully set

  
    return extractBoolean(this.callMethod(FacebookMethod.PROFILE_SET_FBML,
                          new Pair<String, CharSequence>("uid", Integer.toString(userId)),
                          new Pair<String, CharSequence>("markup", fbmlMarkup)));

  
public voidsetDebug(boolean isDebug)

    _debug = isDebug;
  
public static voidsetDebugAll(boolean isDebug)

    FacebookRestClient.DEBUG = isDebug;
  
public voidsetIsDesktop(boolean isDesktop)

    this._isDesktop = isDesktop;
  
private static voidstripEmptyTextNodes(org.w3c.dom.Node n)
Hack...since DOM reads newlines as textnodes we want to strip out those nodes to make it easier to use the tree.

    NodeList children = n.getChildNodes();
    int length = children.getLength();
    for (int i = 0; i < length; i++) {
      Node c = children.item(i);
      if (!c.hasChildNodes() && c.getNodeType() == Node.TEXT_NODE &&
          c.getTextContent().trim().length() == 0) {
        n.removeChild(c);
        i--;
        length--;
        children = n.getChildNodes();
      }
      else {
        stripEmptyTextNodes(c);
      }
    }
  
public org.w3c.dom.Documentusers_getInfo(java.util.Collection userIds, java.util.EnumSet fields)
Retrieves the requested info fields for the requested set of users.

param
userIds a collection of user IDs for which to fetch info
param
fields a set of ProfileFields
return
a Document consisting of a list of users, with each user element containing the requested fields.

    // assertions test for invalid params
    assert (userIds != null);
    assert (fields != null);
    assert (!fields.isEmpty());

    return this.callMethod(FacebookMethod.USERS_GET_INFO,
                           new Pair<String, CharSequence>("uids", delimit(userIds)),
                           new Pair<String, CharSequence>("fields", delimit(fields)));
  
public org.w3c.dom.Documentusers_getInfo(java.util.Collection userIds, java.util.Set fields)
Retrieves the requested info fields for the requested set of users.

param
userIds a collection of user IDs for which to fetch info
param
fields a set of strings describing the info fields desired, such as "last_name", "sex"
return
a Document consisting of a list of users, with each user element containing the requested fields.

    // assertions test for invalid params
    assert (userIds != null);
    assert (fields != null);
    assert (!fields.isEmpty());

    return this.callMethod(FacebookMethod.USERS_GET_INFO,
                           new Pair<String, CharSequence>("uids", delimit(userIds)),
                           new Pair<String, CharSequence>("fields", delimit(fields)));
  
public intusers_getLoggedInUser()
Retrieves the user ID of the user logged in to this API session

return
the Facebook user ID of the logged-in user

    Document d = this.callMethod(FacebookMethod.USERS_GET_LOGGED_IN_USER);
    return Integer.parseInt(d.getFirstChild().getTextContent());
  
public booleanusers_isAppAdded()
Retrieves an indicator of whether the logged-in user has installed the application associated with the _apiKey.

return
boolean indicating whether the user has installed the app

    return extractBoolean(this.callMethod(FacebookMethod.USERS_IS_APP_ADDED));