illab.nabal.proxy.WeiboProxy.java Source code

Java tutorial

Introduction

Here is the source code for illab.nabal.proxy.WeiboProxy.java

Source

/*
 * Copyright (C) 2013-2014 Tan Jung
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package illab.nabal.proxy;

import illab.nabal.agent.Operation;
import illab.nabal.agent.dto.WeiboPost;
import illab.nabal.agent.dto.WeiboProfile;
import illab.nabal.exception.NetworkException;
import illab.nabal.exception.SystemException;
import illab.nabal.settings.SnsProperties;
import illab.nabal.settings.SocialNetwork;
import illab.nabal.settings.SystemProperties;
import illab.nabal.util.ParameterHelper;
import illab.nabal.util.StringHelper;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;

import android.content.Context;
import android.text.TextUtils;

/**
 * Implementations of Weibo APIs.
 * 
 * @version 1.0, 02/10/14
 * @author <a href="mailto:tanito.jung@gmail.com">Tan Jung</a>
 */
class WeiboProxy extends AbstractProxy implements WeiboDelegate {
    //private final static String TAG = "WeiboProxy";

    /**
     * Weibo web domain.
     */
    private final static String WEB_HOME_URL = "http://weibo.com/";

    /**
     * Dummy integer parameter for unspecified count.
     */
    private final static int UNSPECIFIED_COUNT = 0;

    /**
     * Dummy integer parameter for unspecified cursor.
     */
    private final static int UNSPECIFIED_CURSOR = -1;

    /**
     * Dummy integer parameter for unspecified page.
     */
    private final static int UNSPECIFIED_PAGE = 0;

    /**
     * Dummy integer parameter for unspecified post ID.
     */
    private final static long UNSPECIFIED_POST_ID = -1L;

    /**
     * Weibo network context.
     */
    private final WeiboContext mWeiboContext;

    /**
     * Constructor for Weibo covert op proxy.
     * 
     * @param context
      * @param systemProperties
      * @param snsProperties
     */
    WeiboProxy(Context context, SystemProperties systemProperties, SnsProperties snsProperties) {
        mContext = context;
        mWeiboContext = (WeiboContext) (mNetworkContext = new WeiboContext(mContext, new NetworkSessionListener(),
                systemProperties, snsProperties));
    }

    /**
     * Constructor for Weibo proxy.
     * 
     * @param alias
     * @param context
      * @param systemProperties
      * @param snsProperties
     */
    WeiboProxy(String alias, Context context, SystemProperties systemProperties, SnsProperties snsProperties) {
        mContext = context;
        mWeiboContext = (WeiboContext) (mNetworkContext = new WeiboContext(alias, mContext,
                new NetworkSessionListener(), systemProperties, snsProperties));
    }

    /**
     * Inject a Weibo session.
     * 
     * @param accessToken
     */
    void injectSession(String accessToken) {
        mWeiboContext.injectSession(accessToken);
    }

    /* START OF ***************** API implementations ***********************/

    @Override
    public void getMyProfile(final Operation<WeiboDelegate, WeiboProfile> operation) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getProfileByUid(""));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getProfileByUid(final Operation<WeiboDelegate, WeiboProfile> operation, final String userUid) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getProfileByUid(userUid));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getProfileByDomain(final Operation<WeiboDelegate, WeiboProfile> operation,
            final String domainName) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getProfileByDomain(domainName));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getFriendCount(final Operation<WeiboDelegate, JSONArray> operation, final String[] userUids) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getFriendCount(userUids));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getAllMyFriendUids(final Operation<WeiboDelegate, JSONObject> operation) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyFriendUids(UNSPECIFIED_COUNT, UNSPECIFIED_CURSOR));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getMyFriendUids(final Operation<WeiboDelegate, JSONObject> operation, final int count,
            final int cursor) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyFriendUids(count, cursor));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getAllMyFriends(final Operation<WeiboDelegate, List<WeiboProfile>> operation) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyFriends(UNSPECIFIED_COUNT, UNSPECIFIED_CURSOR));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getMyFriends(final Operation<WeiboDelegate, List<WeiboProfile>> operation, final int count,
            final int cursor) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyFriends(count, cursor));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getAllMyBilateralFriendUids(final Operation<WeiboDelegate, JSONObject> operation) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyBilateralFriendUids(UNSPECIFIED_COUNT, UNSPECIFIED_CURSOR));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getMyBilateralFriendUids(final Operation<WeiboDelegate, JSONObject> operation, final int count,
            final int cursor) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyBilateralFriendUids(count, cursor));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getAllMyBilateralFriends(final Operation<WeiboDelegate, List<WeiboProfile>> operation) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyBilateralFriends(UNSPECIFIED_COUNT, UNSPECIFIED_CURSOR));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getMyBilateralFriends(final Operation<WeiboDelegate, List<WeiboProfile>> operation, final int count,
            final int cursor) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyBilateralFriends(count, cursor));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getAllCommonFriends(final Operation<WeiboDelegate, List<WeiboProfile>> operation,
            final String userUid) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getCommonFriends(userUid, UNSPECIFIED_COUNT, UNSPECIFIED_CURSOR));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getCommonFriends(final Operation<WeiboDelegate, List<WeiboProfile>> operation, final String userUid,
            final int count, final int cursor) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getCommonFriends(userUid, count, cursor));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getAllMyFollowerUids(final Operation<WeiboDelegate, JSONObject> operation) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyFollowerUids(UNSPECIFIED_COUNT, UNSPECIFIED_CURSOR));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getMyFollowerUids(final Operation<WeiboDelegate, JSONObject> operation, final int count,
            final int cursor) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyFollowerUids(count, cursor));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getAllMyFollowers(final Operation<WeiboDelegate, List<WeiboProfile>> operation) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyFollowers(UNSPECIFIED_COUNT, UNSPECIFIED_CURSOR));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getMyFollowers(final Operation<WeiboDelegate, List<WeiboProfile>> operation, final int count,
            final int cursor) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMyFollowers(count, cursor));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getRelationship(final Operation<WeiboDelegate, JSONObject> operation, final String sourceUserUid,
            final String targetUserUid) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getRelationship(sourceUserUid, targetUserUid));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void followUser(final Operation<WeiboDelegate, WeiboProfile> operation, final String userUid) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(followUser(userUid));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void unfollowUser(final Operation<WeiboDelegate, WeiboProfile> operation, final String userUid) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(unfollowUser(userUid));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void remarkFriend(final Operation<WeiboDelegate, WeiboProfile> operation, final String userUid,
            final String remark) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(remarkFriend(userUid, remark));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getHomeTimeline(final Operation<WeiboDelegate, List<WeiboPost>> operation, final int count,
            final int page, final int feature) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(
                            getHomeTimeline(UNSPECIFIED_POST_ID, UNSPECIFIED_POST_ID, count, page, feature));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getHomeTimeline(final Operation<WeiboDelegate, List<WeiboPost>> operation, final long sincePostId,
            final long maxPostId, final int count, final int page, final int feature) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getHomeTimeline(sincePostId, maxPostId, count, page, feature));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getMyTimeline(final Operation<WeiboDelegate, List<WeiboPost>> operation, final int count,
            final int page, final int feature, final boolean needUserData) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getUserTimeline("", UNSPECIFIED_POST_ID, UNSPECIFIED_POST_ID, count, page,
                            feature, needUserData));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getMyTimeline(final Operation<WeiboDelegate, List<WeiboPost>> operation, final long sincePostId,
            final long maxPostId, final int count, final int page, final int feature, final boolean needUserData) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(
                            getUserTimeline("", sincePostId, maxPostId, count, page, feature, needUserData));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getUserTimeline(final Operation<WeiboDelegate, List<WeiboPost>> operation, final String userUid,
            final int count, final int page, final int feature, final boolean needUserData) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getUserTimeline(userUid, UNSPECIFIED_POST_ID, UNSPECIFIED_POST_ID, count,
                            page, feature, needUserData));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getUserTimeline(final Operation<WeiboDelegate, List<WeiboPost>> operation, final String userUid,
            final long sincePostId, final long maxPostId, final int count, final int page, final int feature,
            final boolean needUserData) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(
                            getUserTimeline(userUid, sincePostId, maxPostId, count, page, feature, needUserData));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getRepostTimeline(final Operation<WeiboDelegate, List<WeiboPost>> operation,
            final long originalPostId, final int count, final int page, final int authorFilter) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getRepostTimeline(originalPostId, UNSPECIFIED_POST_ID, UNSPECIFIED_POST_ID,
                            count, page, authorFilter));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getRepostTimeline(final Operation<WeiboDelegate, List<WeiboPost>> operation,
            final long originalPostId, final long sincePostId, final long maxPostId, final int count,
            final int page, final int authorFilter) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(
                            getRepostTimeline(originalPostId, sincePostId, maxPostId, count, page, authorFilter));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getRepostsByMe(final Operation<WeiboDelegate, List<WeiboPost>> operation, final long sincePostId,
            final long maxPostId, final int count, final int page) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getRepostsByMe(sincePostId, maxPostId, count, page));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getMentions(final Operation<WeiboDelegate, List<WeiboPost>> operation, final long sincePostId,
            final long maxPostId, final int count, final int page, final int authorFilter, final int sourceFilter,
            final int typeFilter) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getMentions(sincePostId, maxPostId, count, page, authorFilter, sourceFilter,
                            typeFilter));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getBilateralFriendTimeline(final Operation<WeiboDelegate, List<WeiboPost>> operation,
            final long sincePostId, final long maxPostId, final int count, final int page, final int feature) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getBilateralFriendTimeline(sincePostId, maxPostId, count, page, feature));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getPost(final Operation<WeiboDelegate, WeiboPost> operation, final long postId) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getPost(postId));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void postStatus(final Operation<WeiboDelegate, WeiboPost> operation, final String status,
            final float latitude, final float longitude, final JSONArray annotations) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(postStatus(status, latitude, longitude, annotations));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void repostStatus(final Operation<WeiboDelegate, WeiboPost> operation, final long originalPostId,
            final String status, final int commentOption) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(repostStatus(originalPostId, status, commentOption));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void deleteStatus(final Operation<WeiboDelegate, WeiboPost> operation, final long postId) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(deleteStatus(postId));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void postPhoto(final Operation<WeiboDelegate, WeiboPost> operation, final String absolutePathOfPhoto,
            final String status, final float latitude, final float longitude, final JSONArray annotations) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(postPhoto(absolutePathOfPhoto, status, latitude, longitude, annotations));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void postPhotoFromUrl(final Operation<WeiboDelegate, WeiboPost> operation, final String photoUrl,
            final String status, final float latitude, final float longitude, final JSONArray annotations) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(postPhotoFromUrl(photoUrl, status, latitude, longitude, annotations));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getComments(final Operation<WeiboDelegate, List<WeiboPost>> operation, final long parentPostId,
            final long sincePostId, final long maxPostId, final int count, final int page, final int authorFilter) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation
                            .onResult(getComments(parentPostId, sincePostId, maxPostId, count, page, authorFilter));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getCommentsByMe(final Operation<WeiboDelegate, List<WeiboPost>> operation, final long sincePostId,
            final long maxPostId, final int count, final int page, final int sourceFilter) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(getCommentsByMe(sincePostId, maxPostId, count, page, sourceFilter));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void getCommentsToMe(final Operation<WeiboDelegate, List<WeiboPost>> operation, final long sincePostId,
            final long maxPostId, final int count, final int page, final int authorFilter, final int sourceFilter) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(
                            getCommentsToMe(sincePostId, maxPostId, count, page, authorFilter, sourceFilter));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void postComment(final Operation<WeiboDelegate, WeiboPost> operation, final long parentPostId,
            final String comment, final int commentOption) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(postComment(parentPostId, comment, commentOption));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });
    }

    @Override
    public void deleteComment(final Operation<WeiboDelegate, WeiboPost> operation, final long commentId) {
        requestJob(new ProxyJob() {
            public void onFail(Exception e) {
                operation.onFail(e);
            }

            public void run() {
                try {
                    operation.onResult(deleteComment(commentId));
                } catch (Exception e) {
                    onFail(e);
                }
            }
        });

    }

    /**
     * Get a Weibo profile corresponding to given UID.
     * 
     * @param userUid
     * @return WeiboProfile
     * @throws Exception
     */
    private WeiboProfile getProfileByUid(String userUid) throws Exception {

        String apiUri = "/users/show.json";

        // if no user UID is assigned, use the current user's UID
        String uid = userUid;
        if (StringHelper.isEmpty(uid) == true) {
            uid = mWeiboContext.getUid();
        }

        return populateProfileBean(getResponseJson(
                getHttpGet(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("uid", uid))));
    }

    /**
     * Get a Weibo profile corresponding to given Weibo URL.
     * 
     * @param domainName
     * @return WeiboProfile
     * @throws Exception
     */
    private WeiboProfile getProfileByDomain(String domainName) throws Exception {

        String apiUri = "/users/domain_show.json";

        // throw an exception if no domain name is given 
        if (domainName == null || domainName.length() == 0) {
            throw new SystemException("Invalid domain name.");
        }

        // get rid of host in case full URL is given
        // (e.g. http://weibo.com/myweibodomain -> myweibodomain)
        String domain = domainName.replace(WEB_HOME_URL, "");

        return populateProfileBean(getResponseJson(
                getHttpGet(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("domain", domain))));
    }

    /**
     * Get Weibo users' friend count.
     * 
     * @param userUids
     * @return JSONArray
     * @throws Exception
     */
    private JSONArray getFriendCount(String[] userUids) throws Exception {

        String apiUri = "/users/counts.json";

        // throw an exception if no user UID is given 
        if (userUids == null || userUids.length == 0) {
            throw new SystemException("Invalid user UIDs.");
        }

        // join user UIDs and make a CSV
        String commaSeparatedUids = TextUtils.join(",", userUids);

        return getJsonArray(getResponseString(
                getHttpGet(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("uids", commaSeparatedUids))));
    }

    /**
     * Get UIDs of my Weibo friends.
     * 
     * @param count how many friends per page
     * @param cursor where to start indexing pages
     * @return JSONObject
     * @throws Exception
     */
    private JSONObject getMyFriendUids(int count, int cursor) throws Exception {

        String apiUri = "/friendships/friends/ids.json";

        List<NameValuePair> params = ParameterHelper
                .addAllParams(new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()));

        // set page parameters
        setProfilePageParams(params, count, cursor);

        return getResponseJson(getHttpGet(apiUri, params));
    }

    /**
     * Get my Weibo friends.
     * 
     * @param count how many friends per page
     * @param cursor where to start indexing pages
     * @return list of WeiboProfile objects
     * @throws Exception
     */
    private List<WeiboProfile> getMyFriends(int count, int cursor) throws Exception {

        String apiUri = "/friendships/friends.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("uid", mWeiboContext.getUid()));

        // set page parameters
        setProfilePageParams(params, count, cursor);

        return populateProfileList(getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get UIDs of my bilateral Weibo friends.
     * 
     * @param count how many friends per page
     * @param cursor where to start indexing pages
     * @return JSONObject
     * @throws Exception
     */
    private JSONObject getMyBilateralFriendUids(int count, int cursor) throws Exception {

        String apiUri = "/friendships/friends/bilateral/ids.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("uid", mWeiboContext.getUid()));

        // set page parameters
        setProfilePageParams(params, count, cursor);

        return getResponseJson(getHttpGet(apiUri, params));
    }

    /**
     * Get my bilateral Weibo friends.
     * 
     * @param count how many friends per page
     * @param cursor where to start indexing pages
     * @return list of WeiboProfile objects
     * @throws Exception
     */
    private List<WeiboProfile> getMyBilateralFriends(int count, int cursor) throws Exception {

        String apiUri = "/friendships/friends/bilateral.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("uid", mWeiboContext.getUid()));

        // set page parameters
        setProfilePageParams(params, count, cursor);

        return populateProfileList(getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get common friends between given UID.
     * 
     * @param count how many friends per page
     * @param cursor where to start indexing pages
     * @return list of WeiboProfile objects
     * @throws Exception
     */
    private List<WeiboProfile> getCommonFriends(String userUid, int count, int cursor) throws Exception {

        String apiUri = "/friendships/friends/in_common.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("uid", mWeiboContext.getUid()), new BasicNameValuePair("suid", userUid));

        // set page parameters
        setProfilePageParams(params, count, cursor);

        return populateProfileList(getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get UIDs of my Weibo followers.
     * 
     * @param count how many followers per page
     * @param cursor where to start indexing pages
     * @return JSONObject
     * @throws Exception
     */
    private JSONObject getMyFollowerUids(int count, int cursor) throws Exception {

        String apiUri = "/friendships/followers/ids.json";

        List<NameValuePair> params = ParameterHelper
                .addAllParams(new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()));

        // set page parameters
        setProfilePageParams(params, count, cursor);

        return getResponseJson(getHttpGet(apiUri, params));
    }

    /**
     * Get my Weibo followers.
     * 
     * @param count how many followers per page
     * @param cursor where to start indexing pages
     * @return list of WeiboProfile objects
     * @throws Exception
     */
    private List<WeiboProfile> getMyFollowers(int count, int cursor) throws Exception {

        String apiUri = "/friendships/followers.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("uid", mWeiboContext.getUid()));

        // set page parameters
        setProfilePageParams(params, count, cursor);

        return populateProfileList(getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get relationship of two Weibo users.
     * 
     * @param sourceUserUid
     * @param targetUserUid
     * @return JSONObject
     * @throws Exception
     */
    private JSONObject getRelationship(String sourceUserUid, String targetUserUid) throws Exception {

        String apiUri = "/friendships/show.json";

        if (StringHelper.isAllFull(sourceUserUid, targetUserUid) == false) {
            throw new SystemException("Invalid user UIDs.");
        }

        return getResponseJson(
                getHttpGet(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("source_id", sourceUserUid),
                        new BasicNameValuePair("target_id", targetUserUid)));
    }

    /**
     * Follow a Weibo user.
     * 
     * @param userUid
     * @return WeiboProfile
     * @throws Exception
     */
    private WeiboProfile followUser(String userUid) throws Exception {

        String apiUri = "/friendships/create.json";

        return populateProfileBean(getResponseJson(
                getHttpPost(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("uid", userUid))));
    }

    /**
     * Unfollow a Weibo user.
     * 
     * @param userUid
     * @return WeiboProfile
     * @throws Exception
     */
    private WeiboProfile unfollowUser(String userUid) throws Exception {

        String apiUri = "/friendships/destroy.json";

        return populateProfileBean(getResponseJson(
                getHttpPost(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("uid", userUid))));
    }

    /**
     * Update a remark of a Weibo friend.
     * 
     * @param userUid
     * @param remark
     * @return WeiboProfile
     * @throws Exception
     */
    private WeiboProfile remarkFriend(String userUid, String remark) throws Exception {

        String apiUri = "/friendships/remark/update.json";

        return populateProfileBean(getResponseJson(
                getHttpPost(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("uid", userUid), new BasicNameValuePair("remark", remark))));
    }

    /**
     * Get home timeline of posts posted by me and my Weibo friends.
     * 
     * @param sincePostId
     * @param maxPostId
     * @param count
     * @param page
     * @param feature
     * @return list of WeiboPost objects
     * @throws Exception
     */
    private List<WeiboPost> getHomeTimeline(long sincePostId, long maxPostId, int count, int page, int feature)
            throws Exception {

        String apiUri = "/statuses/home_timeline.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("feature", "" + feature));

        // set page parameters
        setTimelinePageParams(params, sincePostId, maxPostId, count, page);

        return populatePostList("statuses", getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get user's timeline.
     * 
     * @param userUid
     * @param sincePostId
     * @param maxPostId
     * @param count
     * @param page
     * @param feature
     * @param needUserData
     * @return list of WeiboPost objects
     * @throws Exception
     */
    private List<WeiboPost> getUserTimeline(String userUid, long sincePostId, long maxPostId, int count, int page,
            int feature, boolean needUserData) throws Exception {

        String apiUri = "/statuses/user_timeline.json";

        // if no user UID is assigned, use the current user's UID
        String uid = userUid;
        if (StringHelper.isEmpty(uid) == true) {
            uid = mWeiboContext.getUid();
        }

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("uid", uid), new BasicNameValuePair("feature", "" + feature),
                new BasicNameValuePair("trim_user", (needUserData) ? "0" : "1"));

        // set page parameters
        setTimelinePageParams(params, sincePostId, maxPostId, count, page);

        return populatePostList("statuses", getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get repost timeline.
     * 
     * @param originalPostId
     * @param sincePostId
     * @param maxPostId
     * @param count
     * @param page
     * @param authorFilter
     * @return list of WeiboPost objects
     * @throws Exception
     */
    private List<WeiboPost> getRepostTimeline(long originalPostId, long sincePostId, long maxPostId, int count,
            int page, int authorFilter) throws Exception {

        String apiUri = "/statuses/repost_timeline.json";

        // throw an exception if original post ID is invalid
        if (originalPostId <= 0) {
            throw new SystemException("Invalid original post Id.");
        }

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("id", "" + originalPostId),
                new BasicNameValuePair("filter_by_author", "" + authorFilter));

        // set page parameters
        setTimelinePageParams(params, sincePostId, maxPostId, count, page);

        return populatePostList("reposts", getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get reposted posts by me.
     * 
     * @param sincePostId
     * @param maxPostId
     * @param count
     * @param page
     * @return list of posts reposted by me
     * @throws Exception
     */
    private List<WeiboPost> getRepostsByMe(long sincePostId, long maxPostId, int count, int page) throws Exception {

        String apiUri = "/statuses/repost_by_me.json";

        List<NameValuePair> params = ParameterHelper
                .addAllParams(new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()));

        // set page parameters
        setTimelinePageParams(params, sincePostId, maxPostId, count, page);

        return populatePostList("reposts", getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get posts mentioned me.
     * 
     * @param sincePostId
     * @param maxPostId
     * @param count
     * @param page
     * @param authorFilter
     * @param sourceFilter
     * @param typeFilter
     * @return list of posts mentioned me
     * @throws Exception
     */
    private List<WeiboPost> getMentions(long sincePostId, long maxPostId, int count, int page, int authorFilter,
            int sourceFilter, int typeFilter) throws Exception {

        String apiUri = "/statuses/mentions.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("filter_by_author", "" + authorFilter),
                new BasicNameValuePair("filter_by_source", "" + sourceFilter),
                new BasicNameValuePair("filter_by_type", "" + typeFilter));

        // set page parameters
        setTimelinePageParams(params, sincePostId, maxPostId, count, page);

        return populatePostList("statuses", getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get posts from bialteral friends.
     * 
     * @param sincePostId
     * @param maxPostId
     * @param count
     * @param page
     * @param feature
     * @return list of WeiboPost objects
     * @throws Exception
     */
    private List<WeiboPost> getBilateralFriendTimeline(long sincePostId, long maxPostId, int count, int page,
            int feature) throws Exception {

        String apiUri = "/statuses/bilateral_timeline.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("feature", "" + feature));

        // set page parameters
        setTimelinePageParams(params, sincePostId, maxPostId, count, page);

        return populatePostList("statuses", getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get a Weibo post.
     * 
     * @param postId
     * @return a Weibo post corresponding to given post ID
     * @throws Exception
     */
    private WeiboPost getPost(long postId) throws Exception {

        String apiUri = "/statuses/show.json";

        return populatePostBean(getResponseJson(
                getHttpGet(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("id", "" + postId))));
    }

    /**
     * Post a Weibo post.
     * 
     * @param message
     * @param latitude from -90.0 to +90.0; +: North latitude;Default is 0.0
     * @param longitude from -180.0 to +180.0; +: East longitude;Default is 0.0
     * @param annotations notes/metadatas for your application
     * @return a WeiboPost object cotaining content you've just posted
     * @throws Exception
     */
    private WeiboPost postStatus(String message, float latitude, float longitude, JSONArray annotations)
            throws Exception {

        String apiUri = "/statuses/update.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("status", message), new BasicNameValuePair("lat", "" + latitude),
                new BasicNameValuePair("long", "" + longitude));

        if (annotations != null && annotations.length() > 0) {
            params.add(new BasicNameValuePair("annotations", annotations.toString()));
        }

        return populatePostBean(getResponseJson(getHttpPost(apiUri, params)));
    }

    /**
     * Repost a Weibo post.
     * 
     * @param originalPostId
     * @param message
     * @param commentOption
     * @return a WeiboPost object cotaining content you've just reposted
     * @throws Exception
     */
    private WeiboPost repostStatus(long originalPostId, String message, int commentOption) throws Exception {

        String apiUri = "/statuses/repost.json";

        // throw an exception if original post ID is invalid
        if (originalPostId <= 0) {
            throw new SystemException("Invalid original post Id.");
        }

        return populatePostBean(getResponseJson(getHttpPost(apiUri,
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("id", "" + originalPostId), new BasicNameValuePair("status", message),
                new BasicNameValuePair("is_comment", "" + commentOption))));
    }

    /**
     * Delete a Weibo post.
     * 
     * @param postId
     * @return a WeiboPost object cotaining post data you've just deleted
     * @throws Exception
     */
    private WeiboPost deleteStatus(long postId) throws Exception {

        String apiUri = "/statuses/destroy.json";

        // throw an exception if post ID is invalid
        if (postId <= 0) {
            throw new SystemException("Invalid post Id.");
        }

        return populatePostBean(getResponseJson(
                getHttpPost(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("id", "" + postId))));
    }

    /**
     * Post a photo.
     * 
     * @param absolutePathOfPhoto
     * @param message
     * @param latitude
     * @param longitude
     * @param annotations
     * @return a WeiboPost object cotaining post data you've just created
     * @throws Exception
     */
    private WeiboPost postPhoto(String absolutePathOfPhoto, String message, float latitude, float longitude,
            JSONArray annotations) throws Exception {

        String apiUri = "/statuses/upload.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("status", message), new BasicNameValuePair("lat", "" + latitude),
                new BasicNameValuePair("long", "" + longitude));

        if (annotations != null && annotations.length() > 0) {
            params.add(new BasicNameValuePair("annotations", annotations.toString()));
        }

        return populatePostBean(getResponseJson(getMultipartHttpPost(apiUri, params, "pic", absolutePathOfPhoto)));
    }

    /**
     * Post a photo.
     * 
     * @param photoUrl
     * @param message
     * @param latitude
     * @param longitude
     * @param annotations
     * @return a WeiboPost object cotaining post data you've just created
     * @throws Exception
     */
    private WeiboPost postPhotoFromUrl(String photoUrl, String message, float latitude, float longitude,
            JSONArray annotations) throws Exception {

        String apiUri = "/statuses/upload_url_text.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("url", photoUrl), new BasicNameValuePair("status", message),
                new BasicNameValuePair("lat", "" + latitude), new BasicNameValuePair("long", "" + longitude));

        if (annotations != null && annotations.length() > 0) {
            params.add(new BasicNameValuePair("annotations", annotations.toString()));
        }

        return populatePostBean(getResponseJson(getHttpPost(apiUri, params)));
    }

    /**
     * Get comments.
     * 
     * @param parentPostId
     * @param sincePostId
     * @param maxPostId
     * @param count
     * @param page
     * @param authorFilter
     * @return list of comments attached to given post ID
     * @throws Exception
     */
    private List<WeiboPost> getComments(long parentPostId, long sincePostId, long maxPostId, int count, int page,
            int authorFilter) throws Exception {

        String apiUri = "/comments/show.json";

        // throw an exception if parent post ID is invalid
        if (parentPostId <= 0) {
            throw new SystemException("Invalid parent post Id.");
        }

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("id", "" + parentPostId),
                new BasicNameValuePair("filter_by_author", "" + authorFilter));

        // set page parameters
        setTimelinePageParams(params, sincePostId, maxPostId, count, page);

        return populatePostList("comments", getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get comments by me.
     * 
     * @param sincePostId
     * @param maxPostId
     * @param count
     * @param page
     * @param sourceFilter
     * @return list of comments created by me
     * @throws Exception
     */
    private List<WeiboPost> getCommentsByMe(long sincePostId, long maxPostId, int count, int page, int sourceFilter)
            throws Exception {

        String apiUri = "/comments/by_me.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("filter_by_source", "" + sourceFilter));

        // set page parameters
        setTimelinePageParams(params, sincePostId, maxPostId, count, page);

        return populatePostList("comments", getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Get comments by me.
     * 
     * @param sincePostId
     * @param maxPostId
     * @param count
     * @param page
     * @param authorFilter
     * @param sourceFilter
     * @return list of comments created to me
     * @throws Exception
     */
    private List<WeiboPost> getCommentsToMe(long sincePostId, long maxPostId, int count, int page, int authorFilter,
            int sourceFilter) throws Exception {

        String apiUri = "/comments/to_me.json";

        List<NameValuePair> params = ParameterHelper.addAllParams(
                new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                new BasicNameValuePair("filter_by_author", "" + authorFilter),
                new BasicNameValuePair("filter_by_source", "" + sourceFilter));

        // set page parameters
        setTimelinePageParams(params, sincePostId, maxPostId, count, page);

        return populatePostList("comments", getResponseJson(getHttpGet(apiUri, params)));
    }

    /**
     * Post a comment to a Weibo post.
     * 
     * @param parentPostId
     * @param comment
     * @param commentOption
     * @return a WeiboPost object cotaining comment data you've just created
     * @throws Exception
     */
    private WeiboPost postComment(long parentPostId, String comment, int commentOption) throws Exception {

        String apiUri = "/comments/create.json";

        // throw an exception if parent post ID is invalid
        if (parentPostId <= 0) {
            throw new SystemException("Invalid parent post Id.");
        }

        return populatePostBean(getResponseJson(
                getHttpPost(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("id", "" + parentPostId), new BasicNameValuePair("comment", comment),
                        new BasicNameValuePair("comment_ori", "" + commentOption))));
    }

    /**
     * Delete a comment.
     * 
     * @param commentId
     * @return a WeiboPost object cotaining comment data you've just deleted
     * @throws Exception
     */
    private WeiboPost deleteComment(long commentId) throws Exception {

        String apiUri = "/comments/destroy.json";

        // throw an exception if comment ID is invalid
        if (commentId <= 0) {
            throw new SystemException("Invalid comment Id.");
        }

        return populatePostBean(getResponseJson(
                getHttpPost(apiUri, new BasicNameValuePair("access_token", mWeiboContext.getAccessToken()),
                        new BasicNameValuePair("cid", "" + commentId))));
    }

    /* END OF ****************** API implementations ************************/

    /**
     * Set count and cursor parameters for Weibo profile list.
     * 
     * @param params
     * @param count
     * @param cursor
     * @return params
     */
    private List<NameValuePair> setProfilePageParams(List<NameValuePair> params, int count, int cursor) {

        // page capacity must be greater than 0
        if (count > UNSPECIFIED_COUNT) {
            params.add(new BasicNameValuePair("count", "" + count));
        }

        // if cursor is given
        if (cursor > UNSPECIFIED_CURSOR) {
            params.add(new BasicNameValuePair("cursor", "" + cursor));
        }

        return params;
    }

    /**
     * Set since_id, max_id, count and page parameters for Weibo timeline.
     * 
     * @param params
     * @param sincePostId
     * @param maxPostId
     * @param count
     * @param page
     * @return params
     */
    private List<NameValuePair> setTimelinePageParams(List<NameValuePair> params, long sincePostId, long maxPostId,
            int count, int page) {

        // if since_id is given
        if (sincePostId > UNSPECIFIED_POST_ID) {
            params.add(new BasicNameValuePair("since_id", "" + sincePostId));
        }

        // if max_id is given
        if (maxPostId > UNSPECIFIED_POST_ID) {
            params.add(new BasicNameValuePair("max_id", "" + maxPostId));
        }

        // page capacity must be greater than 0
        if (count > UNSPECIFIED_COUNT) {
            params.add(new BasicNameValuePair("count", "" + count));
        }

        // page number must be greater than 0
        if (page > UNSPECIFIED_PAGE) {
            params.add(new BasicNameValuePair("page", "" + page));
        }

        return params;
    }

    /**
     * Get WeiboProfile list from JSON array.
     * 
     * @param responseJson
     * @return profileList
     * @throws Exception
     */
    private List<WeiboProfile> populateProfileList(JSONObject responseJson) throws Exception {

        JSONArray profileJsonArray = responseJson.optJSONArray("users");

        // profile list must not be empty
        if (profileJsonArray == null || profileJsonArray.length() == 0) {
            throw new NetworkException("Profile list is empty.", responseJson.toString());
        }

        // iterate profile list and populate WeiboProfile beans
        List<WeiboProfile> profileList = new ArrayList<WeiboProfile>();
        for (int i = 0; i < profileJsonArray.length(); i++) {
            profileList.add(populateProfileBean(profileJsonArray.getJSONObject(i)));
        }

        return profileList;
    }

    /**
     * Set Weibo profile data to a WeiboProfile bean.
     * 
     * @param profileJson
     * @return a WeiboProfile bean
     * @throws Exception
     */
    private WeiboProfile populateProfileBean(JSONObject profileJson) throws Exception {

        // throw an exception if JSON is invalid
        if (profileJson == null || profileJson.has("idstr") == false) {
            if (profileJson == null) {
                throw new NetworkException("Profile JSON is null and cannot populate a Profile bean.");
            } else {
                throw new NetworkException("Invalid profile JSON.", profileJson.toString());
            }
        }

        // set profile data
        WeiboProfile weiboProfile = new WeiboProfile();
        weiboProfile.setSnsUid(SocialNetwork.WEIBO);
        weiboProfile.setProfileJson(profileJson);
        weiboProfile.setUid(profileJson.optString("idstr"));
        weiboProfile.setUserName(profileJson.optString("screen_name"));
        weiboProfile.setFullName(profileJson.optString("name"));
        weiboProfile.setProfilePageUrl(WEB_HOME_URL + profileJson.optString("profile_url"));
        weiboProfile.setSmallProfilePhotoUrl(profileJson.optString("profile_image_url"));
        weiboProfile.setLargeProfilePhotoUrl(profileJson.optString("avatar_hd"));

        // set last post data
        if (profileJson.has("status") == true) {
            JSONObject postJson = profileJson.getJSONObject("status");
            WeiboPost lastPost = new WeiboPost();
            lastPost.setSnsUid(SocialNetwork.WEIBO);
            lastPost.setPostJson(postJson);
            lastPost.setPostId(postJson.optLong("id"));
            lastPost.setPosterUid(profileJson.optString("idstr"));
            lastPost.setPosterUserName(profileJson.optString("screen_name"));
            lastPost.setPosterFullName(profileJson.optString("name"));
            lastPost.setTextContent(postJson.optString("text"));
            lastPost.setRepostCount(postJson.optInt("reposts_count"));
            lastPost.setCommentCount(postJson.optInt("comments_count"));
            lastPost.setLikeCount(postJson.optInt("attitudes_count"));
            lastPost.setCreatedDate(postJson.optString("created_at"));
            weiboProfile.setLastPost(lastPost);
        }

        return weiboProfile;
    }

    /**
     * Get WeiboPost list from JSON array.
     * 
     * @param keyName
     * @param responseJson
     * @return postList
     * @throws Exception
     */
    private List<WeiboPost> populatePostList(String keyName, JSONObject responseJson) throws Exception {

        JSONArray postJsonArray = responseJson.optJSONArray(keyName);

        // post list must not be empty
        if (postJsonArray == null || postJsonArray.length() == 0) {
            throw new NetworkException("Post list is empty.", responseJson.toString());
        }

        // iterate post list and populate WeiboPost beans
        List<WeiboPost> postList = new ArrayList<WeiboPost>();
        for (int i = 0; i < postJsonArray.length(); i++) {
            postList.add(populatePostBean(postJsonArray.getJSONObject(i)));
        }

        return postList;
    }

    /**
     * Set Weibo post data to a WeiboPost bean.
     * 
     * @param postJson
     * @return weiboPost
     * @throws Exception
     */
    private WeiboPost populatePostBean(JSONObject postJson) throws Exception {

        // throw an exception if JSON is invalid
        if (postJson == null || postJson.has("id") == false) {
            if (postJson == null) {
                throw new NetworkException("Post JSON is null and cannot populate a Post bean.");
            } else {
                throw new NetworkException("Invalid post JSON.", postJson.toString());
            }
        }

        // set post data
        WeiboPost weiboPost = new WeiboPost();
        weiboPost.setSnsUid(SocialNetwork.WEIBO);
        weiboPost.setPostJson(postJson);
        weiboPost.setPostId(postJson.optLong("id"));
        weiboPost.setTextContent(postJson.optString("text"));
        weiboPost.setRepostCount(postJson.optInt("reposts_count"));
        weiboPost.setCommentCount(postJson.optInt("comments_count"));
        weiboPost.setLikeCount(postJson.optInt("attitudes_count"));
        weiboPost.setCreatedDate(postJson.optString("created_at"));

        // set poster profile bean
        if (postJson.has("user") == true) {
            WeiboProfile posterProfile = populateProfileBean(postJson.getJSONObject("user"));
            weiboPost.setPosterUid(posterProfile.getUid());
            weiboPost.setPosterFullName(posterProfile.getFullName());
            weiboPost.setPosterUserName(posterProfile.getUserName());
            weiboPost.setPosterProfile(posterProfile);
        }

        // if user data is not provided, look up uid
        else {
            weiboPost.setPosterUid(postJson.optString("uid"));
        }

        // set image URLs if current post has attached images
        if (postJson.has("thumbnail_pic") == true) {
            weiboPost.setThumbnailPhotoUrl(postJson.optString("thumbnail_pic"));
            weiboPost.setMidSizePhotoUrl(postJson.optString("bmiddle_pic"));
            weiboPost.setFullSizePhotoUrl(postJson.optString("original_pic"));
        }

        // set original post if current post is a repost
        if (postJson.has("retweeted_status") == true) {
            weiboPost.setOriginalPost(populatePostBean(postJson.getJSONObject("retweeted_status")));
        }

        // set parent post if current post is a comment
        if (postJson.has("status") == true) {
            weiboPost.setOriginalPost(populatePostBean(postJson.getJSONObject("status")));
        }

        return weiboPost;
    }

}