/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.demo.implementations.comment;

import com.socialize.CommentUtils;
import com.socialize.demo.SDKDemoActivity;
import com.socialize.entity.Comment;
import com.socialize.entity.ListResult;
import com.socialize.error.SocializeException;
import com.socialize.listener.comment.CommentListListener;

/**
 * @author Jason Polites
 *
 */
public class GetCommentsByEntityActivity extends SDKDemoActivity {

	/* (non-Javadoc)
	 * @see com.socialize.demo.DemoActivity#executeDemo()
	 */
	@Override
	public void executeDemo(String text) {

		CommentUtils.getCommentsByEntity(this, entity.getKey(), 0, PAGE_SIZE, new CommentListListener() {

			@Override
			public void onList(ListResult<Comment> comments) {
				handleSocializeResult(comments);
			}

			@Override
			public void onError(SocializeException error) {
				handleError(GetCommentsByEntityActivity.this, error);
			}
		});
	}

	@Override
	public boolean isTextEntryRequired() {
		return false;
	}

	/* (non-Javadoc)
	 * @see com.socialize.demo.DemoActivity#getButtonText()
	 */
	@Override
	public String getButtonText() {
		return "List " + PAGE_SIZE + " Comments for Current Entity";
	}
}


/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.util;

import android.graphics.Bitmap;
import android.util.DisplayMetrics;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

/**
 * @author Jason Polites
 */
public class BitmapUtils {

	private BitmapBuilder bitmapBuilder;
	private Base64Utils base64Utils;
	private int defaultDensity = DisplayMetrics.DENSITY_DEFAULT;

	public BitmapUtils(BitmapBuilder bitmapBuilder) {
		super();
		this.bitmapBuilder = bitmapBuilder;
	}

	public BitmapUtils() {
		super();
	}

	public Bitmap getScaledBitmap(byte[] data, int scaleToWidth, int scaleToHeight) {
		return getScaledBitmap(bitmapBuilder.decode(data), scaleToWidth, scaleToHeight, defaultDensity);
	}

	public Bitmap getScaledBitmap(InputStream in, int scaleToWidth, int scaleToHeight) {
		return getScaledBitmap(bitmapBuilder.decode(in), scaleToWidth, scaleToHeight, defaultDensity);
	}

	public Bitmap getScaledBitmap(Bitmap bitmap, int scaleToWidth, int scaleToHeight) {
		return getScaledBitmap(bitmap, scaleToWidth, scaleToHeight, true, defaultDensity);
	}

	public Bitmap getScaledBitmap(byte[] data, int scaleToWidth, int scaleToHeight, int density) {
		return getScaledBitmap(bitmapBuilder.decode(data), scaleToWidth, scaleToHeight, density);
	}

	public Bitmap getScaledBitmap(InputStream in, int scaleToWidth, int scaleToHeight, int density) {
		return getScaledBitmap(bitmapBuilder.decode(in), scaleToWidth, scaleToHeight, density);
	}

	public Bitmap getScaledBitmap(Bitmap bitmap, int scaleToWidth, int scaleToHeight, int density) {
		return getScaledBitmap(bitmap, scaleToWidth, scaleToHeight, true, density);
	}

	public String encode(Bitmap bitmap) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); //bm is the bitmap object
        byte[] image = baos.toByteArray();
        return base64Utils.encode(image);

	}

	/**
	 * Returns a scaled bitmap, cropped if necessary.
	 * @param bitmap
	 * @param scaleToWidth
	 * @param scaleToHeight
	 * @param recycleOriginal
	 * @return
	 */
	public Bitmap getScaledBitmap(Bitmap bitmap, int scaleToWidth, int scaleToHeight, boolean recycleOriginal, int density) {

		bitmap.setDensity(density);
		Bitmap original = bitmap;

		if (scaleToWidth > 0 || scaleToHeight > 0) {

			int width = bitmap.getWidth();
			int height = bitmap.getHeight();

			// scale lowest and crop highes
			if (height != scaleToHeight || width != scaleToWidth) {

				float ratio = 1.0f;

				// Scale to smallest
				if (height > width) {

					ratio = (float) scaleToWidth / (float) width;
					width = scaleToWidth;
					height = Math.round((float) height * ratio);

					bitmap = bitmapBuilder.scale(bitmap, width, height);

					width = bitmap.getWidth();
					height = bitmap.getHeight();

					if (height > scaleToHeight) {
						// crop height
						int diff = height - scaleToHeight;
						int half = Math.round((float) diff / 2.0f);

						bitmap = bitmapBuilder.crop(bitmap, 0, half, width, scaleToHeight);
					}
				}
				else {

					ratio = (float) scaleToHeight / (float) height;
					height = scaleToHeight;
					width = Math.round((float) width * ratio);

					bitmap = bitmapBuilder.scale(bitmap, width, height);

					width = bitmap.getWidth();
					height = bitmap.getHeight();

					if (width > scaleToWidth) {
						// crop width
						int diff = width - scaleToWidth;
						int half = Math.round((float) diff / 2.0f);
						bitmap = bitmapBuilder.crop(bitmap, half, 0, scaleToWidth, height);
					}
				}

				if(recycleOriginal) {
					original.recycle();
				}
			}
		}

		return bitmap;
	}

	public void setBitmapBuilder(BitmapBuilder bitmapBuilder) {
		this.bitmapBuilder = bitmapBuilder;
	}

	public void setBase64Utils(Base64Utils base64Utils) {
		this.base64Utils = base64Utils;
	}
}


/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.api;

import android.content.Context;
import android.location.Location;
import com.socialize.Socialize;
import com.socialize.api.action.ActionOptions;
import com.socialize.api.action.ActionType;
import com.socialize.api.action.ShareType;
import com.socialize.auth.*;
import com.socialize.concurrent.ManagedAsyncTask;
import com.socialize.config.SocializeConfig;
import com.socialize.entity.*;
import com.socialize.error.SocializeException;
import com.socialize.listener.AuthProviderListener;
import com.socialize.listener.SocializeActionListener;
import com.socialize.listener.SocializeAuthListener;
import com.socialize.location.SocializeLocationProvider;
import com.socialize.log.SocializeLogger;
import com.socialize.networks.SocialNetwork;
import com.socialize.notifications.NotificationChecker;
import com.socialize.provider.SocializeProvider;
import com.socialize.ui.profile.UserSettings;
import com.socialize.util.AppUtils;
import com.socialize.util.HttpUtils;
import com.socialize.util.StringUtils;

import java.util.List;
import java.util.Map;

/**
 * @author Jason Polites
 *
 * @param <T>
 * @param <P>
 */
public class SocializeApi<T extends SocializeObject, P extends SocializeProvider<T>> {

	private P provider;
	private SocializeResponseFactory<T> responseFactory;
	private AuthProviders authProviders;
	private SocializeLogger logger;
	private HttpUtils httpUtils;
	private SocializeLocationProvider locationProvider;
	private NotificationChecker notificationChecker;
	private AppUtils appUtils;
	protected SocializeConfig config;

	public static enum RequestType {AUTH,PUT,POST,PUT_AS_POST,GET,LIST,LIST_AS_GET,LIST_WITHOUT_ENTITY,DELETE};

	public SocializeApi(P provider) {
		super();
		this.provider = provider;
	}

	public void clearSession() {
		provider.clearSession();
	}

	public void clearSession(AuthProviderType type) {
		provider.clearSession(type);
	}

	public SocializeSession loadSession(String endpoint, String key, String secret) throws SocializeException {
		return provider.loadSession(endpoint, key, secret);
	}

	public SocializeSession authenticate(Context context, String endpoint, String key, String secret, String uuid, String advertiserId) throws SocializeException {
		SocializeSession session = provider.authenticate(endpoint, key, secret, uuid, advertiserId);
		checkNotifications(context, session);

		return session;
	}

	public SocializeSession authenticate(Context context, String endpoint, String key, String secret, AuthProviderData data, String udid, String advertiserId) throws SocializeException {
		SocializeSession session = provider.authenticate(endpoint, key, secret, data, udid, advertiserId);
		checkNotifications(context, session);
		return session;
	}

	protected void checkNotifications(Context context, SocializeSession session) {
		if(notificationChecker != null) {
			notificationChecker.checkRegistrations(context, session);
		}
	}

	protected void setPropagationData(SocializeAction action, ActionOptions shareOptions, SocialNetwork...networks) {

		boolean selfManaged = (shareOptions == null) ? false : shareOptions.isSelfManaged();

		if(networks != null) {
			Propagation propagation = null;
			Propagation localPropagation = null;

			for (SocialNetwork socialNetwork : networks) {
				if(socialNetwork.isLocalPropagation() || selfManaged) {
					if(localPropagation == null) {
						localPropagation = newPropagation();
					}
					localPropagation.addThirdParty(socialNetwork);
				}
				else {
					if(propagation == null) {
						propagation = newPropagation();
					}
					propagation.addThirdParty(socialNetwork);
				}
			}

			if(config != null) {
				String appStore = config.getProperty(SocializeConfig.REDIRECT_APP_STORE);

				if(!StringUtils.isEmpty(appStore)) {

					String abbrev = appUtils.getAppStoreAbbreviation(appStore);

					if(localPropagation != null) {
						localPropagation.addExtraParam("f", abbrev);
					}

					if(propagation != null) {
						propagation.addExtraParam("f", abbrev);
					}
				}

				String ogAction = null;

				switch(action.getActionType()) {
					case LIKE:
						if(config.isOGLike()) {
							ogAction = "like";
						}
						break;
				}

				if(ogAction != null) {
					if(propagation != null) {
						propagation.addExtraParam("og_action", ogAction);
					}

					if(localPropagation != null) {
						localPropagation.addExtraParam("og_action", ogAction);
					}
				}
			}

			action.setPropagation(propagation);
			action.setPropagationInfoRequest(localPropagation);
		}
	}

	protected void setPropagationData(SocializeAction action, ShareType shareType) {
		if(shareType != null) {
			Propagation localPropagation = newPropagation();
			localPropagation.addThirdParty(shareType);
			String appStore = null;

			if(config != null) {
				appStore = config.getProperty(SocializeConfig.REDIRECT_APP_STORE);
			}

			if(!StringUtils.isEmpty(appStore)) {
				String abbrev = appUtils.getAppStoreAbbreviation(appStore);
				localPropagation.addExtraParam("f", abbrev);
			}

			action.setPropagationInfoRequest(localPropagation);
		}
	}

	// Mockable
	protected Propagation newPropagation() {
		return new Propagation();
	}

	public ListResult<T> list(SocializeSession session, String endpoint, String key, String...ids) throws SocializeException {
		return provider.list(session, endpoint, key, ids, 0, SocializeConfig.MAX_LIST_RESULTS);
	}

	public ListResult<T> list(SocializeSession session, String endpoint, String key, String idKey, Map<String, String> extraParams, int startIndex, int endIndex, String...ids) throws SocializeException {
		return provider.list(session, endpoint, key, ids, idKey, extraParams, startIndex, endIndex);
	}

	public ListResult<T> list(SocializeSession session, String endpoint, String key, int startIndex, int endIndex, String...ids) throws SocializeException {
		return provider.list(session, endpoint, key, ids, startIndex, endIndex);
	}

	public ListResult<T> list(SocializeSession session, String endpoint) throws SocializeException {
		return provider.list(session, endpoint, 0, SocializeConfig.MAX_LIST_RESULTS);
	}

	public ListResult<T> list(SocializeSession session, String endpoint, int startIndex, int endIndex) throws SocializeException {
		return provider.list(session, endpoint, startIndex, endIndex);
	}

	public T get(SocializeSession session, String endpoint, String id) throws SocializeException {
		return provider.get(session, endpoint, id);
	}

	public T get(SocializeSession session, String endpoint, String id, ActionType type) throws SocializeException {
		return provider.get(session, endpoint, id, type);
	}

	public void delete(SocializeSession session, String endpoint, String id) throws SocializeException {
		provider.delete(session, endpoint, id);
	}

	public ListResult<T> put(SocializeSession session, String endpoint, T object) throws SocializeException {
		return provider.put(session, endpoint, object);
	}

	public ListResult<T> put(SocializeSession session, String endpoint, List<T> objects) throws SocializeException {
		return provider.put(session, endpoint, objects);
	}

	public ListResult<T> post(SocializeSession session, String endpoint, T object, boolean isJSONResponse) throws SocializeException {
		return provider.post(session, endpoint, object, isJSONResponse);
	}

	public ListResult<T> post(SocializeSession session, String endpoint, List<T> objects) throws SocializeException {
		return post(session, endpoint, objects, true);
	}

	public ListResult<T> post(SocializeSession session, String endpoint, List<T> objects, boolean isJSONResponse) throws SocializeException {
		return provider.post(session, endpoint, objects, isJSONResponse);
	}

	public T putAsPost(SocializeSession session, String endpoint, T object) throws SocializeException {
		return provider.putAsPost(session, endpoint, object);
	}

	public void listAsync(SocializeSession session, String endpoint, String key, int startIndex, int endIndex, SocializeActionListener listener, String...ids) {
		listAsync(session, endpoint, key,  "id", null, startIndex, endIndex, listener, ids);
	}

	public void listAsync(SocializeSession session, String endpoint, String key, String idKey, Map<String, String> extraParams, int startIndex, int endIndex, SocializeActionListener listener, String...ids) {
		AsyncGetter getter = new AsyncGetter(session, listener);
		SocializeGetRequest request = new SocializeGetRequest();
		request.setEndpoint(endpoint);
		request.setRequestType(RequestType.LIST);
		request.setExtraParams(extraParams);
		request.setKey(key);
		request.setIds(ids);
		request.setIdKey(idKey);
		request.setStartIndex(startIndex);
		request.setEndIndex(endIndex);
		getter.execute(request);
	}

	public void listAsync(SocializeSession session, String endpoint, String key, SocializeActionListener listener, String...ids) {
		listAsync(session, endpoint, key, 0, SocializeConfig.MAX_LIST_RESULTS, listener, ids);
	}

	public void listAsync(SocializeSession session, String endpoint, int startIndex, int endIndex, SocializeActionListener listener) {
		AsyncGetter getter = new AsyncGetter(session, listener);
		SocializeGetRequest request = new SocializeGetRequest();
		request.setRequestType(RequestType.LIST_WITHOUT_ENTITY);
		request.setEndpoint(endpoint);
		request.setStartIndex(startIndex);
		request.setEndIndex(endIndex);
		getter.execute(request);
	}

	public void listAsync(SocializeSession session, String endpoint, SocializeActionListener listener) {
		listAsync(session, endpoint, 0, SocializeConfig.MAX_LIST_RESULTS, listener);
	}

	public void getByEntityAsync(SocializeSession session, String endpoint, String key, SocializeActionListener listener) {
		AsyncGetter getter = new AsyncGetter(session, listener);
		SocializeGetRequest request = new SocializeGetRequest();
		request.setRequestType(RequestType.LIST);
		request.setEndpoint(endpoint);
		request.setKey(key);
		getter.execute(request);
	}

	public void getAsync(SocializeSession session, String endpoint, String id, SocializeActionListener listener) {
		AsyncGetter getter = new AsyncGetter(session, listener);
		SocializeGetRequest request = new SocializeGetRequest();
		request.setRequestType(RequestType.GET);
		request.setEndpoint(endpoint);
		request.setIds(id);
		getter.execute(request);
	}

	public void deleteAsync(SocializeSession session, String endpoint, String id, SocializeActionListener listener) {
		AsyncGetter getter = new AsyncGetter(session, listener);
		SocializeGetRequest request = new SocializeGetRequest();
		request.setRequestType(RequestType.DELETE);
		request.setEndpoint(endpoint);
		request.setIds(id);
		getter.execute(request);
	}

	@SuppressWarnings("unchecked")
	public void putAsync(SocializeSession session, String endpoint, T object, SocializeActionListener listener) {
		AsyncPutter poster = new AsyncPutter(session, listener);
		SocializePutRequest<T> request = new SocializePutRequest<T>();
		request.setRequestType(RequestType.PUT);
		request.setEndpoint(endpoint);
		request.setObject(object);
		poster.execute(request);
	}

	@SuppressWarnings("unchecked")
	public void putAsync(SocializeSession session, String endpoint, List<T> objects, SocializeActionListener listener) {
		AsyncPutter poster = new AsyncPutter(session, listener);
		SocializePutRequest<T> request = new SocializePutRequest<T>();
		request.setRequestType(RequestType.PUT);
		request.setEndpoint(endpoint);
		request.setObjects(objects);
		poster.execute(request);
	}

	public void postAsync(SocializeSession session, String endpoint, T object, SocializeActionListener listener) {
		postAsync(session, endpoint, object, true, listener);
	}

	@SuppressWarnings("unchecked")
	public void postAsync(SocializeSession session, String endpoint, T object, boolean jsonResponse, SocializeActionListener listener) {
		AsyncPutter poster = new AsyncPutter(session, listener);
		SocializePutRequest<T> request = new SocializePutRequest<T>();
		request.setRequestType(RequestType.POST);
		request.setEndpoint(endpoint);
		request.setObject(object);
		request.setJsonResponse(jsonResponse);
		poster.execute(request);
	}

	public void postAsync(SocializeSession session, String endpoint, List<T> objects, SocializeActionListener listener) {
		postAsync(session, endpoint, objects, true, listener);
	}

	@SuppressWarnings("unchecked")
	public void postAsync(SocializeSession session, String endpoint, List<T> objects, boolean jsonResponse, SocializeActionListener listener) {
		AsyncPutter poster = new AsyncPutter(session, listener);
		SocializePutRequest<T> request = new SocializePutRequest<T>();
		request.setRequestType(RequestType.POST);
		request.setEndpoint(endpoint);
		request.setObjects(objects);
		request.setJsonResponse(jsonResponse);
		poster.execute(request);
	}

	/**
	 * Does a POST, but expects a single object in return.
	 * @param session
	 * @param endpoint
	 * @param object
	 * @param listener
	 */
	@SuppressWarnings("unchecked")
	public void putAsPostAsync(SocializeSession session, String endpoint, T object, SocializeActionListener listener) {
		AsyncPutter poster = new AsyncPutter(session, listener);
		SocializePutRequest<T> request = new SocializePutRequest<T>();
		request.setRequestType(RequestType.PUT_AS_POST);
		request.setEndpoint(endpoint);
		request.setObject(object);
		poster.execute(request);
	}

	public void authenticateAsync(
			Context context,
			String key,
			String secret,
			String uuid,
			String androidId,
			final AuthProviderData data,
			final SocializeAuthListener listener,
			final SocializeSessionConsumer sessionConsumer,
			boolean do3rdPartyAuth) {

		SocializeActionListener wrapper = null;

		final SocializeAuthListener localListener = new SocializeAuthListener() {

			@Override
			public void onError(SocializeException error) {
				if(listener != null) {
					listener.onError(error);
				}
				else {
					if(logger != null) {
						logger.error("Failure during auth", error);
					}
				}
			}

			@Override
			public void onCancel() {
				if(listener != null) {
					listener.onCancel();
				}
			}

			@Override
			public void onAuthSuccess(SocializeSession session) {
				if(sessionConsumer != null) {
					sessionConsumer.setSession(session);
				}
				if(listener != null) {
					listener.onAuthSuccess(session);
				}
			}

			@Override
			public void onAuthFail(SocializeException error) {
				if(listener != null) {
					listener.onAuthFail(error);
				}
				else {
					if(logger != null) {
						logger.error("Failure during auth", error);
					}
				}
			}
		};

		wrapper = new SocializeActionListener() {

			@Override
			public void onResult(RequestType type, SocializeResponse response) {
				SocializeAuthResponse authResponse = (SocializeAuthResponse) response;
				localListener.onAuthSuccess(authResponse.getSession());
			}

			@Override
			public void onError(SocializeException error) {
				if(httpUtils != null && httpUtils.isAuthError(error)) {
					localListener.onAuthFail(error);
				}
				else {
					localListener.onError(error);
				}
			}
		};

		final SocializeAuthRequest request = new SocializeAuthRequest();

		request.setEndpoint("/authenticate/");
		request.setConsumerKey(key);
		request.setConsumerSecret(secret);
		request.setUdid(uuid);
		request.setAdvertiserId(androidId);
		request.setAuthProviderData(data);

		AuthProviderType authProviderType = getAuthProviderType(data);

		if(do3rdPartyAuth && !authProviderType.equals(AuthProviderType.SOCIALIZE)) {
			handle3rdPartyAuth(context, request, wrapper, localListener, key, secret);
		}
		else {
			// Do normal auth
			handleRegularAuth(context, request, wrapper, localListener, key, secret);
		}
	}

	protected AuthProviderType getAuthProviderType(AuthProviderData data) {
		if(data == null) {
			return AuthProviderType.SOCIALIZE;
		}

		AuthProviderType authProviderType = null;

		AuthProviderInfo authProviderInfo = data.getAuthProviderInfo();

		if(authProviderInfo != null) {
			authProviderType = authProviderInfo.getType();
		}

		return authProviderType;
	}

	protected void validate(AuthProviderData data) throws SocializeException {
		AuthProviderInfo authProviderInfo = data.getAuthProviderInfo();

		if(authProviderInfo != null) {
			authProviderInfo.validate();
		}
		else {
			throw new SocializeException("Empty auth provider info");
		}
	}

	protected void handleRegularAuth(Context context, SocializeAuthRequest request, SocializeActionListener wrapper, SocializeAuthListener listener, String key, String secret) {
		AsyncAuthenicator authenicator = new AsyncAuthenicator(context, null, wrapper);
		authenicator.execute(request);
	}

	protected void handle3rdPartyAuth(
			final Context context,
			final SocializeAuthRequest request,
			final SocializeActionListener wrapper,
			final SocializeAuthListener listener,
			final String key,
			final String secret)  {

		final AuthProviderData authProviderData = request.getAuthProviderData();

		// Try loading the session first
		SocializeSession session = null;

		AuthProviderType authProviderType = getAuthProviderType(authProviderData);

		try {
			validate(authProviderData);
		}
		catch (SocializeException error) {
			if(listener != null) {
				listener.onError(error);
			}
			else if(logger != null) {
				logger.error("Error validating auth provider data", error);
			}
		}

		try {
			session = loadSession(request.getEndpoint(), key, secret);
		}
		catch (SocializeException e) {
			// No need to throw this, just log it
			logger.warn("Failed to load saved session data", e);
		}

		if(session == null || !provider.validateSession(session, authProviderData)) {
			// Get the provider for the type
			AuthProvider<AuthProviderInfo> authProvider = authProviders.getProvider(authProviderType);

			if(authProvider != null) {

				AuthProviderListener authProviderListener = new AuthProviderListener() {

					@Override
					public void onError(SocializeException error) {
						if(listener != null) {
							listener.onError(error);
						}
					}

					@Override
					public void onAuthSuccess(AuthProviderResponse response) {
						authProviderData.setUserId3rdParty(response.getUserId());
						authProviderData.setToken3rdParty(response.getToken());
						authProviderData.setSecret3rdParty(response.getSecret());

						// Do normal auth (forced)
						handleRegularAuth(context, request, wrapper, listener, key, secret);
					}

					@Override
					public void onAuthFail(SocializeException error) {
						if(listener != null) {
							listener.onAuthFail(error);
						}
					}

					@Override
					public void onCancel() {
						if(listener != null) {
							listener.onCancel();
						}
					}
				};

				AuthProviderInfo authProviderInfo = authProviderData.getAuthProviderInfo();

				if(authProviderInfo != null) {
					authProvider.authenticate(context, authProviderInfo, authProviderListener);
				}
				else {
					if(listener != null) {
						listener.onError(new SocializeException("Authentication failed.  No AuthProviderInfo found"));
					}

					logger.error("No AuthProviderInfo found during auth");
				}
			}
			else {
				logger.error("No provider found for auth type [" +
						authProviderType.getName() +
						"]");
			}
		}
		else {
			// We already have a session
			// then just call the listener
			if(listener != null) {
				listener.onAuthSuccess(session);
			}
		}
	}

	public void setResponseFactory(SocializeResponseFactory<T> responseFactory) {
		this.responseFactory = responseFactory;
	}

	public void setAppUtils(AppUtils appUtils) {
		this.appUtils = appUtils;
	}

	public void setConfig(SocializeConfig config) {
		this.config = config;
	}

	public void setNotificationChecker(NotificationChecker notificationChecker) {
		this.notificationChecker = notificationChecker;
	}

	public void setAuthProviders(AuthProviders authProviders) {
		this.authProviders = authProviders;
	}

	public void setLogger(SocializeLogger logger) {
		this.logger = logger;
	}

	public void setHttpUtils(HttpUtils httpUtils) {
		this.httpUtils = httpUtils;
	}

	public void setLocationProvider(SocializeLocationProvider locationProvider) {
		this.locationProvider = locationProvider;
	}

	abstract class AbstractAsyncProcess<Params extends SocializeRequest, Progress, Result extends SocializeResponse> extends ManagedAsyncTask<Params, Progress, Result> {

		RequestType requestType;
		SocializeSession session;
		Exception error = null;
		SocializeActionListener listener = null;
		Context context;

		public AbstractAsyncProcess(Context context, SocializeSession session, SocializeActionListener listener) {
			this(session, listener);
			this.context = context;
		}

		public AbstractAsyncProcess(SocializeSession session, SocializeActionListener listener) {
			super();
			this.session = session;
			this.listener = listener;
		}

		@Override
		protected final Result doInBackground(Params... params) {
			Params request = params[0];
			this.requestType = request.getRequestType();

			Result result = null;
			try {
				result = doInBackground(request);
			}
			catch (Exception error) {
				this.error = error;
			}

			return result;
		}

		@Override
		protected void onPostExecuteManaged(Result result) {
			if(listener != null) {
				if(error != null) {
					listener.onError(SocializeException.wrap(error));
				}
				else {
					listener.onResult(requestType, result);
				}
			}
		}

		protected abstract Result doInBackground(Params param) throws SocializeException;
	}

	class AsyncAuthenicator extends AbstractAsyncProcess<SocializeAuthRequest, Void, SocializeAuthResponse> {

		public AsyncAuthenicator(Context context, SocializeSession session, SocializeActionListener listener) {
			super(context, session, listener);
		}

		@Override
		protected SocializeAuthResponse doInBackground(final SocializeAuthRequest request) throws SocializeException {
			SocializeAuthResponse response = null;

			if(responseFactory != null) {
				response = responseFactory.newAuthResponse();
			}
			else {
				response = new SocializeAuthResponse();
			}

			SocializeSession session;

			AuthProviderData authProviderData = request.getAuthProviderData();
			AuthProviderType authProviderType = getAuthProviderType(authProviderData);

			if(authProviderType == null || authProviderType.equals(AuthProviderType.SOCIALIZE)) {
				session = SocializeApi.this.authenticate(context, request.getEndpoint(), request.getConsumerKey(), request.getConsumerSecret(), request.getUdid(), request.getAdvertiserId());
			}
			else {
				session = SocializeApi.this.authenticate(context, request.getEndpoint(), request.getConsumerKey(), request.getConsumerSecret(), authProviderData, request.getUdid(), request.getAdvertiserId());
			}

			response.setSession(session);

			return response;
		}
	}

	protected void setLocation(SocializeAction action) {
		Location location = null;
		if(locationProvider != null) {
			location = locationProvider.getLastKnownLocation();
		}
		if(location != null) {
			action.setLon(location.getLongitude());
			action.setLat(location.getLatitude());
		}

		SocializeSession session = Socialize.getSocialize().getSession();

		if(session != null) {
			UserSettings settings = session.getUserSettings();

			if(settings != null) {
				action.setLocationShared(settings.isLocationEnabled());
			}
		}
	}

	class AsyncPutter extends AbstractAsyncProcess<SocializePutRequest<T>, Void, SocializeEntityResponse<T>> {
		public AsyncPutter(SocializeSession session, SocializeActionListener listener) {
			super(session, listener);
		}

		@Override
		protected SocializeEntityResponse<T> doInBackground(SocializePutRequest<T> request) throws SocializeException {

			SocializeEntityResponse<T> response = null;

			if(responseFactory != null) {
				response = responseFactory.newEntityResponse();
			}
			else {
				response = new SocializeEntityResponse<T>();
			}

			response.setResultsExpected( request.isJsonResponse() );

			ListResult<T> results = null;

			switch (requestType) {

			case POST:

				if(request.getObjects() != null) {
					results = SocializeApi.this.post(session, request.getEndpoint(), request.getObjects(), request.isJsonResponse());
				}
				else if(request.getObject() != null) {
					results = SocializeApi.this.post(session, request.getEndpoint(), request.getObject(), request.isJsonResponse());
				}

				response.setResults(results);

				break;

			case PUT:

				if(request.getObjects() != null) {
					results = SocializeApi.this.put(session, request.getEndpoint(), request.getObjects());
				}
				else if(request.getObject() != null) {
					results = SocializeApi.this.put(session, request.getEndpoint(), request.getObject());
				}

				response.setResults(results);

				break;

			case PUT_AS_POST:

				if(request.getObject() != null) {
					T result = SocializeApi.this.putAsPost(session, request.getEndpoint(), request.getObject());
					response.addResult(result);
				}
			}

			return response;
		}

		@Override
		protected void onPostExecuteManaged(SocializeEntityResponse<T> result) {
			if(listener != null) {
				if(error != null) {
					listener.onError(SocializeException.wrap(error));
				}
				else {
					try {
						handleResults(result, logger);
						listener.onResult(requestType, result);
					}
					catch (SocializeException e) {
						listener.onError(e);
					}
				}
			}
		}
	}

	public static final <T extends SocializeObject> void handleResults(SocializeEntityResponse<T> result, SocializeLogger logger) throws SocializeException {
		ListResult<T> results = result.getResults();

		if(results != null) {
			List<T> items = results.getItems();
			List<ActionError> errors = results.getErrors();

			if((items == null || items.size() == 0) && result.isResultsExpected()){
				if(errors != null && errors.size() > 0) {
					throw new SocializeException(errors.get(0).getMessage());
				}
				else {
					throw new SocializeException("No results found in response");
				}
			}
			else {
				if(errors != null && errors.size() > 0) {
					for (ActionError actionError : errors) {
						if(logger != null) {
							if(!StringUtils.isEmpty(actionError.getMessage())) {
								logger.warn(actionError.getMessage());
							}
						}
					}
				}
			}
		}
		else if(result.isResultsExpected()) {
			throw new SocializeException("No results found in response");
		}
	}

	class AsyncGetter extends AbstractAsyncProcess<SocializeGetRequest, Void, SocializeEntityResponse<T>> {

		public AsyncGetter(SocializeSession session, SocializeActionListener listener) {
			super(session, listener);
		}

		@Override
		protected SocializeEntityResponse<T> doInBackground(SocializeGetRequest request) throws SocializeException {

			SocializeEntityResponse<T> response = null;

			if(responseFactory != null) {
				response = responseFactory.newEntityResponse();
			}
			else {
				response = new SocializeEntityResponse<T>();
			}

			ListResult<T> results = null;

			switch (requestType) {

			case GET:
				T result = SocializeApi.this.get(session, request.getEndpoint(), request.getIds()[0]);
				response.addResult(result);
				break;

			case LIST:
				results = SocializeApi.this.list(session, request.getEndpoint(), request.getKey(), request.getIdKey(), request.getExtraParams(), request.getStartIndex(), request.getEndIndex(), request.getIds());
				response.setResults(results);
				break;

			case LIST_AS_GET:
				results = SocializeApi.this.list(session, request.getEndpoint(), request.getKey(), request.getIdKey(), request.getExtraParams(), request.getStartIndex(), request.getEndIndex(), request.getIds());
				response.setResults(results);
				break;

			case LIST_WITHOUT_ENTITY:
				results = SocializeApi.this.list(session, request.getEndpoint(), request.getStartIndex(), request.getEndIndex());
				response.setResults(results);
				break;

			case DELETE:
				SocializeApi.this.delete(session, request.getEndpoint(), request.getIds()[0]);
				break;
			}

			return response;
		}
	}
}


/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.ui.actionbar;

import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import com.socialize.entity.Entity;
import com.socialize.log.SocializeLogger;
import com.socialize.ui.comment.OnCommentViewActionListener;
import com.socialize.ui.view.EntityView;

/**
 * @author Jason Polites
 */
public class ActionBarView extends EntityView {

	public static final int ACTION_BAR_HEIGHT = 44;
	public static final int ACTION_BAR_BUTTON_WIDTH = 80;

	private ActionBarLayoutView actionBarLayoutView;
	private ActionBarListener actionBarListener;

	private ActionBarOptions actionBarOptions;

	private Entity entity;

	private OnActionBarEventListener onActionBarEventListener;
	private OnCommentViewActionListener onCommentViewActionListener;

	public ActionBarView(Context context) {
		super(context);
	}

	public ActionBarView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	public View getLoadingView() {
		ActionBarLoadingView loadingView = new ActionBarLoadingView(getContext());
		loadingView.init(getActivity());
		return loadingView;
	}

	/* (non-Javadoc)
	 * @see com.socialize.ui.view.EntityView#getView(android.os.Bundle, java.lang.Object[])
	 */
	@Override
	protected View getView(Bundle bundle, Object... entityKeys) {
		if(actionBarLayoutView == null) {

			actionBarLayoutView = container.getBean("actionBarLayoutView", this, actionBarOptions);

			if(actionBarLayoutView == null) {
				SocializeLogger.w("Request for bean [actionBarLayoutView] returned null");
			}
		}

		setListeners();

		if(actionBarListener != null) {
			actionBarListener.onCreate(this);
		}

		return actionBarLayoutView;
	}

	protected void setListeners() {
		if(actionBarLayoutView != null) {
			if(onActionBarEventListener != null) {
				actionBarLayoutView.setOnActionBarEventListener(onActionBarEventListener);
			}

			if(onCommentViewActionListener != null) {
				actionBarLayoutView.setOnCommentViewActionListener(onCommentViewActionListener);
			}
		}
	}

	public Entity getEntity() {
		return entity;
	}

	public void setEntity(Entity entity) {
		this.entity = entity;
	}

	/* (non-Javadoc)
	 * @see com.socialize.ui.view.EntityView#getEntityKeys()
	 */
	@Override
	protected String[] getBundleKeys() {
		return null;
	}

	@Override
	public void showError(Context context, Exception e) {
		// Don't display popup
		SocializeLogger.e(e.getMessage(), e);
	}

	@Override
	protected View getEditModeView() {
		return new ActionBarEditView(getContext());
	}

	public void setOnActionBarEventListener(OnActionBarEventListener onActionBarEventListener) {
		this.onActionBarEventListener = onActionBarEventListener;
		setListeners();
	}

	public void setOnCommentViewActionListener(OnCommentViewActionListener onCommentViewActionListener) {
		this.onCommentViewActionListener = onCommentViewActionListener;
		setListeners();
	}

	public void refresh() {
		refresh(null);
	}

	public void refresh(OnActionBarReloadListener listener) {
		if(actionBarLayoutView != null) {
			actionBarLayoutView.reload(listener);
		}
	}

	public void stopTicker() {
		if(actionBarLayoutView != null) {
			actionBarLayoutView.stopTicker();
		}
	}

	public void startTicker() {
		if(actionBarLayoutView != null) {
			actionBarLayoutView.startTicker();
		}
	}

	public void setActionBarListener(ActionBarListener actionBarListener) {
		this.actionBarListener = actionBarListener;
	}

	public ActionBarOptions getActionBarOptions() {
		return actionBarOptions;
	}

	public void setActionBarOptions(ActionBarOptions actionBarOptions) {
		this.actionBarOptions = actionBarOptions;
	}
}


/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.networks.facebook.v2;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.HttpMethod;
import com.socialize.android.ioc.IBeanFactory;
import com.socialize.api.SocializeSession;
import com.socialize.auth.AuthProviderType;
import com.socialize.auth.DefaultUserProviderCredentials;
import com.socialize.auth.UserProviderCredentials;
import com.socialize.auth.UserProviderCredentialsMap;
import com.socialize.auth.facebook.FacebookDialogListener;
import com.socialize.auth.facebook.FacebookSessionStore;
import com.socialize.error.SocializeException;
import com.socialize.facebook.AsyncFacebookRunner;
import com.socialize.facebook.AsyncFacebookRunner.RequestListener;
import com.socialize.facebook.Facebook;
import com.socialize.facebook.Facebook.ServiceListener;
import com.socialize.facebook.FacebookError;
import com.socialize.listener.AuthProviderListener;
import com.socialize.listener.ListenerHolder;
import com.socialize.listener.SocializeAuthListener;
import com.socialize.log.SocializeLogger;
import com.socialize.networks.PostData;
import com.socialize.networks.SocialNetwork;
import com.socialize.networks.SocialNetworkListener;
import com.socialize.networks.SocialNetworkPostListener;
import com.socialize.networks.facebook.BaseFacebookFacade;
import com.socialize.networks.facebook.FacebookUtilsProxy;
import com.socialize.networks.facebook.OnPermissionResult;
import com.socialize.util.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * @author Jason Polites
 */
@Deprecated
public class FacebookFacadeV2 extends BaseFacebookFacade {

	private FacebookUtilsProxy facebookUtils;
	private IBeanFactory<AsyncFacebookRunner> facebookRunnerFactory;
	private FacebookSessionStore facebookSessionStore;

	@Override
	public void onActivityResult(Activity context, int requestCode, int resultCode, Intent data) {
		getFacebook(context).authorizeCallback(requestCode, resultCode, data);
	}

	@Override
	public int getSDKMajorVersion() {
		return 2;
	}

	@Override
	public void authenticate(Activity context, String appId, String[] permissions, boolean sso, boolean read, AuthProviderListener listener) {
		authenticate(context, appId, permissions, sso, listener);
	}

	@Deprecated
	@Override
	public void authenticate(final Activity context, String appId, final String[] permissions, final boolean sso, final AuthProviderListener listener) {
		Facebook facebook = getFacebook(context);

		facebookSessionStore.restore(facebook, context);

		FacebookDialogListener facebookDialogListener = new FacebookDialogListener(context, facebook, facebookSessionStore, listener) {

			@Override
			public void onFinish() {
				context.finish();
			}

			@Override
			public void handleError(Throwable error) {
				if(listener != null) {
					listener.onError(new SocializeException(error));
				}
				else {
					error.printStackTrace();
				}
			}
		};

		if(sso) {
			facebook.authorize(context, permissions, facebookDialogListener);
		}
		else {
			facebook.authorize(context, permissions, Facebook.FORCE_DIALOG_AUTH, facebookDialogListener);
		}
	}

	@Override
	public void onResume(Activity context, SocializeAuthListener listener) {
		extendAccessToken(context, listener);
	}

	/* (non-Javadoc)
	 * @see com.socialize.networks.facebook.FacebookFacade#extendAccessToken(android.app.Activity, com.socialize.listener.SocializeAuthListener)
	 */
	@Override
	public void extendAccessToken(final Activity context, final SocializeAuthListener listener) {
		try {
			Facebook facebook = getFacebook(context);
			if(isLinked(context)) {
				if(facebook != null && !facebook.extendAccessTokenIfNeeded(context, new ServiceListener() {
					@Override
					public void onFacebookError(FacebookError e) {
						if(logger != null) {
							logger.warn("An error occurred while attempting to extend a Facebook access token.  The local Facebook account will be cleared.", e);
						}

						// Clear the local session state
						unlink(context, null);
					}

					@Override
					public void onError(Error e) {
						if(logger != null) {
							logger.warn("An error occurred while attempting to extend a Facebook access token.  The local Facebook account will be cleared.", e);
						}

						// Clear the local session state
						unlink(context, null);
					}

					@Override
					public void onComplete(Bundle values) {
						// Update the local session state
						SocializeSession session = getSocialize().getSession();

						if(session != null) {

							final String newAccessToken = values.getString(Facebook.TOKEN);

							if(!StringUtils.isEmpty(newAccessToken)) {

								if(logger != null && logger.isDebugEnabled()) {
									logger.debug("Got new Facebook access token [" +
											newAccessToken +
											"]");
								}

								// Link the user again
								link(context, newAccessToken, false, new SocializeAuthListener() {

									@Override
									public void onError(SocializeException error) {
										if(logger != null) {
											logger.error("An error occurred while attempting to update authentication details", error);
										}

										if(listener != null) {
											listener.onError(error);
										}
									}

									@Override
									public void onCancel() {
										if(listener != null) {
											listener.onCancel();
										}
									}

									@Override
									public void onAuthSuccess(SocializeSession session) {

										UserProviderCredentialsMap map = session.getUserProviderCredentials();

										UserProviderCredentials creds = map.get(AuthProviderType.FACEBOOK);

										DefaultUserProviderCredentials newCreds = new DefaultUserProviderCredentials();

										if(creds != null) {
											newCreds.merge(creds);
										}

										newCreds.setAccessToken(newAccessToken);

										map.put(AuthProviderType.FACEBOOK, newCreds);

										getSocialize().setSession(session);
										getSocialize().saveSession(context);

										if(listener != null) {
											listener.onAuthSuccess(session);
										}
									}

									@Override
									public void onAuthFail(SocializeException error) {
										if(logger != null) {
											logger.error("An error occurred while attempting to update authentication details", error);
										}

										if(listener != null) {
											listener.onAuthFail(error);
										}
									}
								});
							}
							else {
								if(logger != null) {
									logger.warn("Access token returned from Facebook was empty during request to extend");
								}
							}
						}
					}
				})) {
					if(logger != null) {
						logger.warn("Failed to bind to the Facebook RefreshToken Service");
					}
				}
			}
			else if(facebook != null) {
				// Ensure the local fb session is cleared
				String accessToken = facebook.getAccessToken();
				if(!StringUtils.isEmpty(accessToken)) {
					new FacebookSessionStore().clear(context);
				}
			}
		}
		catch (Exception e) {
			if(listener != null) {
				listener.onError(SocializeException.wrap(e));
			}
			if(logger != null) {
				logger.error("Failure during Facebook Token Refresh", e);
			}
		}
	}

	/* (non-Javadoc)
	 * @see com.socialize.networks.facebook.FacebookFacade#post(android.app.Activity, com.socialize.networks.SocialNetworkListener, com.socialize.networks.PostData)
	 */
	@Override
	public void post(Activity parent, SocialNetworkListener listener, PostData postData) {

		boolean okToGo = true;

		if(listener != null) {
			okToGo = !listener.onBeforePost(parent, SocialNetwork.FACEBOOK, postData);
		}

		if(okToGo) {
			Bundle bundle = new Bundle();

			Map<String, Object> postValues = postData.getPostValues();

			if(postValues != null) {

				Set<Entry<String, Object>> entries = postValues.entrySet();

				for (Entry<String, Object> entry : entries) {
					if(entry != null) {
						Object value = entry.getValue();
						String key = entry.getKey();

						if(key != null && value != null) {
							if(value instanceof byte[]) {
								bundle.putByteArray(entry.getKey(), (byte[]) value);
							}
							else {
								bundle.putString(entry.getKey(), value.toString());
							}
						}
					}
				}
			}

			Facebook fb = getFacebook(parent);

			final FacebookSessionStore store = newFacebookSessionStore();

			store.restore(fb, parent);

			AsyncFacebookRunner runner = newAsyncFacebookRunner(fb);

			RequestListener requestListener = newRequestListener(parent, listener);

			String path = postData.getPath();

			if(StringUtils.isEmpty(path)) {
				path = "me/links";
			}

			runner.request(path, bundle, "POST", requestListener, null);
		}
	}

	/* (non-Javadoc)
	 * @see com.socialize.networks.facebook.FacebookFacade#getCurrentPermissions(android.app.Activity, java.lang.String, com.socialize.networks.facebook.v2.FacebookPermissionCallback)
	 */
	@Override
	public void getCurrentPermissions(final Activity parent, String token, final OnPermissionResult callback) {
		Facebook fb = new Facebook(getFacebookAppId());
		fb.setAccessToken(token);
		AsyncFacebookRunner runner = newAsyncFacebookRunner(fb);
		runner.request("me/permissions", new RequestListener() {

			@Override
			public void onMalformedURLException(MalformedURLException e, Object state) {
				handlePermissionError(parent, callback, e);
			}

			@Override
			public void onIOException(IOException e, Object state) {
				handlePermissionError(parent, callback, e);
			}

			@Override
			public void onFileNotFoundException(FileNotFoundException e, Object state) {
				handlePermissionError(parent, callback, e);
			}

			@Override
			public void onFacebookError(FacebookError e, Object state) {
				handlePermissionError(parent, callback, e);
			}

			@Override
			public void onComplete(final String response, final Object state) {
				if(callback != null) {
					parent.runOnUiThread(new Runnable() {
						@Override
						public void run() {
							try {
								JSONObject json = new JSONObject(response);

								if(json.has("data") && !json.isNull("data")) {
									JSONObject data = json.getJSONArray("data").getJSONObject(0);

									// Permissions are keys
									JSONArray names = data.names();

									ArrayList<String> current = new ArrayList<String>();

									for (int i = 0; i < names.length(); i++) {

										// If we're ON we're on
										String permission = names.getString(i);
										int status = data.getInt(permission);

										if(status == 1) {
											// ON
											current.add(permission);
										}
									}

									String[] values = current.toArray(new String[current.size()]);

									Arrays.sort(values); // Sort for binary searching

									callback.onSuccess(values);
								}
							}
							catch (JSONException e) {
								callback.onError(new SocializeException(e));
							}
						}
					});
				}
			}
		});
	}

	/* (non-Javadoc)
	 * @see com.socialize.networks.facebook.FacebookFacade#logout(android.content.Context)
	 */
	@Override
	public void logout(Context context) {
		// Logout does NOT clear the token.. thanks FB :/
		new FacebookSessionStore().clear(context);

		Facebook mFacebook = getFacebook(context);

		try {
			if(mFacebook != null) {
				mFacebook.logout(context);
			}
		}
		catch (Exception e) {
			if(logger != null) {
				logger.error("Failed to log out of Facebook", e);
			}
			else {
				SocializeLogger.e("Failed to log out of Facebook", e);
			}
		}
		finally {
			if(facebookSessionStore != null) {
				facebookSessionStore.clear(context);
			}
		}
	}

	// So we can mock
	protected Facebook getFacebook(Context context) {
		return facebookUtils.getFacebook(context);
	}
	// So we can mock
	protected AsyncFacebookRunner newAsyncFacebookRunner(Facebook fb) {
		if(facebookRunnerFactory != null) {
			return facebookRunnerFactory.getBean(fb);
		}
		return  new AsyncFacebookRunner(fb);
	}
	// So we can mock
	protected FacebookSessionStore newFacebookSessionStore() {
		return new FacebookSessionStore();
	}
	// So we can mock
	protected JSONObject newJSONObject(String response) throws JSONException {
		return new JSONObject(response);
	}
	// So we can mock
	protected RequestListener newRequestListener(final Activity parent, final SocialNetworkPostListener listener) {
		final String defaultErrorMessage = "Facebook Error";

		return new RequestListener() {
			public void onMalformedURLException(MalformedURLException e, Object state) {
				handleFacebookError(parent, 0, defaultErrorMessage, e, listener);
			}
			public void onIOException(IOException e, Object state) {
				handleFacebookError(parent, 0, defaultErrorMessage, e, listener);
			}
			public void onFileNotFoundException(final FileNotFoundException e, Object state) {
				handleFacebookError(parent, 0, defaultErrorMessage, e, listener);
			}
			public void onFacebookError(FacebookError e, Object state) {
				handleFacebookError(parent, 0, defaultErrorMessage, e, listener);
			}
			public void onComplete(final String response, Object state) {

				JSONObject responseObject = null;
				if(!StringUtils.isEmpty(response)) {
					try {
						responseObject = newJSONObject(response);

						if(responseObject.has("error")) {

							JSONObject error = responseObject.getJSONObject("error");

							int code = 0;

							if(error.has("code") && !error.isNull("code")) {
								code = error.getInt("code");
							}

							if(error.has("message") && !error.isNull("message")) {
								String msg = error.getString("message");
								if(logger != null) {
									logger.error(msg);
								}
								else {
									System.err.println(msg);
								}

								handleFacebookError(parent, code, msg, new SocializeException(msg), listener);
							}
							else {
								handleFacebookError(parent, code, defaultErrorMessage, new SocializeException("Facebook Error (Unknown)"), listener);
							}

							return;
						}
					}
					catch (JSONException e) {
						onError(parent, defaultErrorMessage, e, listener);
						return;
					}
				}

				if(listener != null) {
					final JSONObject fResponse = responseObject;
					parent.runOnUiThread(new Runnable() {
						@Override
						public void run() {
							listener.onAfterPost(parent, SocialNetwork.FACEBOOK, fResponse);
						}
					});
				}
			}
		};
	}

	protected void doFacebookCall(Activity parent, Bundle data, String graphPath, HttpMethod method, SocialNetworkPostListener listener) {
		Facebook fb = getFacebook(parent);
		FacebookSessionStore store = newFacebookSessionStore();
		store.restore(fb, parent);
		AsyncFacebookRunner runner = newAsyncFacebookRunner(fb);
		RequestListener requestListener = newRequestListener(parent, listener);
		runner.request(graphPath, data, method.toString(), requestListener, null);
	}

	public void setFacebookUtils(FacebookUtilsProxy facebookUtils) {
		this.facebookUtils = facebookUtils;
	}
	public void setFacebookRunnerFactory(IBeanFactory<AsyncFacebookRunner> facebookRunnerFactory) {
		this.facebookRunnerFactory = facebookRunnerFactory;
	}
	public void setFacebookSessionStore(FacebookSessionStore facebookSessionStore) {
		this.facebookSessionStore = facebookSessionStore;
	}
	public void setHolder(ListenerHolder holder) {
		this.holder = holder;
	}
}


/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.ui.view;

import android.R;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.StateListDrawable;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.socialize.i18n.LocalizationService;
import com.socialize.log.SocializeLogger;
import com.socialize.ui.util.Colors;
import com.socialize.ui.util.CompatUtils;
import com.socialize.util.DisplayUtils;
import com.socialize.util.Drawables;
import com.socialize.util.StringUtils;

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

/**
 * @author Jason Polites
 */
public class SocializeButton extends LinearLayout {

	public static enum TEXT_ALIGN {LEFT, CENTER, RIGHT};

	private LocalizationService localizationService;
	private Drawables drawables;
	private Colors colors;
	private DisplayUtils displayUtils;
	private ImageView imageView = null;
	private TextView textView = null;

	private Integer height = 32;
	private Integer width = null;
	private int textSize = 12;
	private int padding = 0;
	private int textColor = Color.WHITE;

	private int buttonWidth;
	private int buttonHeight;

	private int imagePaddingLeft = 0;
	private int imagePaddingRight = 0;

	@Deprecated
	private String text = "";

	private String textKey;

	private String imageName;

	private boolean bold = false;
	private boolean italic = false;
	private boolean backgroundVisible = true;

	private String bottomColor = Colors.BUTTON_BOTTOM;
	private String topColor = Colors.BUTTON_TOP;
	private String strokeTopColor = Colors.BUTTON_TOP_STROKE;
	private String strokeBottomColor = Colors.BUTTON_BOTTOM_STROKE;
	private String backgroundColor = null;

	private String textAlign = "left";

	private OnClickListener customClickListener;
	private List<OnClickListener> beforeListeners;
	private List<OnClickListener> afterListeners;

	private int textPadding;
	private int cornerRadius = 2;

	private int computedRadius;

	public SocializeButton(Context context) {
		super(context);
	}

	public void init() {
		int dipPadding = 0;
		buttonWidth = LinearLayout.LayoutParams.WRAP_CONTENT;
		buttonHeight = LinearLayout.LayoutParams.WRAP_CONTENT;

		if(displayUtils != null) {
			dipPadding = displayUtils.getDIP(padding);
			computedRadius = displayUtils.getDIP(cornerRadius);
			textPadding = displayUtils.getDIP(4);

			if(width == null) {
				buttonWidth = LinearLayout.LayoutParams.FILL_PARENT;
			}
			else if(width > 0) {
				buttonWidth = displayUtils.getDIP(width);
			}

			if(height == null) {
				buttonHeight = LinearLayout.LayoutParams.FILL_PARENT;
			}
			else if(height > 0) {
				buttonHeight = displayUtils.getDIP(height);
			}
		}

		OnClickListener onClickListener = getOnClickListener();

		LayoutParams fill = makeLayoutParams(buttonWidth, buttonHeight);

		fill.setMargins(dipPadding, dipPadding, dipPadding, dipPadding);

		setOrientation(LinearLayout.HORIZONTAL);
		setLayoutParams(fill);

		setPadding(dipPadding, dipPadding, dipPadding, dipPadding);
		setClickable(true);

		TEXT_ALIGN align = TEXT_ALIGN.LEFT;

		if(!StringUtils.isEmpty(textAlign)) {
			textAlign = textAlign.trim().toUpperCase();
			try {
				align = TEXT_ALIGN.valueOf(textAlign);
			}
			catch (Exception e) {
				SocializeLogger.w(e.getMessage(), e);
			}
		}

		switch (align) {
			case LEFT:
				setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
				break;

			case CENTER:
				setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER);
				break;

			case RIGHT:
				setGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
				break;
		}

		LayoutParams imageLayout = makeLayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
		LayoutParams textLayout = makeLayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);

		textView = makeTextView();
		textView.setTextColor(textColor);

		if(bold) {
			if(italic) {
				textView.setTypeface(Typeface.DEFAULT_BOLD, Typeface.BOLD_ITALIC);
			}
			else {
				textView.setTypeface(Typeface.DEFAULT_BOLD);
			}
		}
		else if(italic) {
			textView.setTypeface(Typeface.DEFAULT, Typeface.ITALIC);
		}

		setTextSize(textSize);

		if(!StringUtils.isEmpty(textKey)) {
			textView.setText(localizationService.getString(textKey));
		}

		textView.setLayoutParams(textLayout);

		if(!StringUtils.isEmpty(imageName)) {

			imageView = makeImageView();
			imageView.setImageDrawable(drawables.getDrawable(imageName));
			imageView.setLayoutParams(imageLayout);

			if(displayUtils != null) {
				imageView.setPadding(displayUtils.getDIP(imagePaddingLeft), 0, displayUtils.getDIP(imagePaddingRight), 0);
			}

			if(!backgroundVisible) {
				imageView.setOnClickListener(onClickListener);
			}

			addView(imageView);

			if(!StringUtils.isEmpty(text)) {
				textView.setPadding(textPadding, 0, 0, 0);
			}
		}
		else {
			textView.setPadding(0, 0, 0, 0);
		}

		if(backgroundVisible) {
			StateListDrawable state = new StateListDrawable();
			state.addState(new int[]{R.attr.state_enabled}, makeEnabledBackgroundDrawable());
			state.addState(new int[]{-R.attr.state_enabled}, makeDisabledBackgroundDrawable());

			CompatUtils.setBackgroundDrawable(this, state);
		}

		addView(textView);

		setOnClickListener(onClickListener);
	}

	protected Drawable makeEnabledBackgroundDrawable() {
        if(colors != null) {
            int bottom = colors.getColor(bottomColor);
            int top = colors.getColor(topColor);
            int strokeTop = colors.getColor(strokeTopColor);
            int strokeBottom = colors.getColor(strokeBottomColor);
            int bgColor = Color.BLACK;

            if(!StringUtils.isEmpty(backgroundColor)) {
                bgColor = colors.getColor(backgroundColor);
            }
            return makeBackgroundDrawable(bgColor, computedRadius, strokeBottom, strokeTop, bottom, top);
        }

        return makeBackgroundDrawable(0, computedRadius, 0, 0, 0, 0);
    }

	protected Drawable makeDisabledBackgroundDrawable() {

        if(colors != null) {
            int bottom = colors.getColor(Colors.BUTTON_DISABLED_BOTTOM);
            int top = colors.getColor(Colors.BUTTON_DISABLED_TOP);
            int strokeTop = colors.getColor(Colors.BUTTON_DISABLED_STROKE);
            int strokeBottom = colors.getColor(Colors.BUTTON_DISABLED_STROKE);
            int bgColor = colors.getColor(Colors.BUTTON_DISABLED_BACKGROUND);
            return makeBackgroundDrawable(bgColor, computedRadius, strokeBottom, strokeTop, bottom, top);
        }

        return null;
	}

	protected Drawable makeBackgroundDrawable(int bgColor, float radius, int strokeBottom, int strokeTop, int bottom, int top) {
		GradientDrawable base = makeGradient(bgColor, bgColor);
        GradientDrawable stroke = makeGradient(strokeBottom, strokeTop);

        if(displayUtils != null) {
            base.setCornerRadius(radius+displayUtils.getDIP(2)); // Add 2 pixels to make it look nicer
            stroke.setCornerRadius(radius+displayUtils.getDIP(1)); // Add 1 pixel to make it look nicer
        }

		GradientDrawable background = makeGradient(bottom, top);

		background.setCornerRadius(radius);

		LayerDrawable layers = new LayerDrawable(new Drawable[] {base, stroke, background});

		layers.setLayerInset(1, 1, 1, 1, 1);
		layers.setLayerInset(2, 2, 2, 2, 2);

		return layers;
	}

	protected OnClickListener getOnClickListener() {
		return new OnClickListener() {
			@Override
			public void onClick(final View v) {

				if(beforeListeners != null) {
					for (OnClickListener listener : beforeListeners) {
						listener.onClick(v);
					}
				}

				if(customClickListener != null) {
					customClickListener.onClick(v);
				}

				if(afterListeners != null) {
					for (OnClickListener listener : afterListeners) {
						listener.onClick(v);
					}
				}
			}
		};
	}

	// use a method so we can mock
	protected ImageView makeImageView() {
		return new ImageView(getContext());
	}
	// use a method so we can mock
	protected TextView makeTextView() {
		return new TextView(getContext());
	}
	// use a method so we can mock
	protected LayoutParams makeLayoutParams(int width, int height) {
		return new LinearLayout.LayoutParams(width, height);
	}

	protected GradientDrawable makeGradient(int bottom, int top) {
		return new GradientDrawable(
				GradientDrawable.Orientation.BOTTOM_TOP,
				new int[] { bottom, top });
	}

	public void setDrawables(Drawables drawables) {
		this.drawables = drawables;
	}

	public void setColors(Colors colors) {
		this.colors = colors;
	}

	public void setDisplayUtils(DisplayUtils deviceUtils) {
		this.displayUtils = deviceUtils;
	}

	public void setHeight(Integer height) {
		this.height = height;
	}

	/**
	 * Set the text size in DIP
	 * @param textSize
	 */
	public void setTextSize(int textSize) {
		if(textView != null) {
			textView.setTextSize(android.util.TypedValue.COMPLEX_UNIT_DIP, textSize);
		}

		this.textSize = textSize;
	}

	@Deprecated
	public void setText(String text) {
		if(textView != null) {
			textView.setText(text);
			textView.setPadding(textPadding, 0, 0, 0);
		}
		this.text = text;
	}

	public void setTextKey(String textKey) {
		if(textView != null) {
			textView.setText(localizationService.getString(textKey));
			textView.setPadding(textPadding, 0, 0, 0);
		}
		this.textKey = textKey;
	}

	public void setBottomColor(String bottomColor) {
		this.bottomColor = bottomColor;
	}

	public void setTopColor(String topColor) {
		this.topColor = topColor;
	}

	public void setStrokeTopColor(String strokeTopColor) {
		this.strokeTopColor = strokeTopColor;
	}

	public void setStrokeBottomColor(String strokeBottomColor) {
		this.strokeBottomColor = strokeBottomColor;
	}

	public void setBackgroundColor(String backgroundColor) {
		this.backgroundColor = backgroundColor;
	}

	public void setImageName(String imageName) {
		this.imageName = imageName;
	}

	public void setWidth(Integer width) {
		this.width = width;
	}

	public void setTextAlign(String textAlign) {
		this.textAlign = textAlign;
	}

	public void setBold(boolean bold) {
		this.bold = bold;
	}

	public void setItalic(boolean italic) {
		this.italic = italic;
	}

	public void setPadding(int padding) {
		this.padding = padding;
	}

	public Integer getButtonHeight() {
		return buttonHeight;
	}

	public Integer getButtonWidth() {
		return buttonWidth;
	}

	public void setCustomClickListener(OnClickListener customClickListener) {
		this.customClickListener = customClickListener;
	}

	public void setImagePaddingLeft(int imagePaddingLeft) {
		this.imagePaddingLeft = imagePaddingLeft;
	}

	public void setImagePaddingRight(int imagePaddingRight) {
		this.imagePaddingRight = imagePaddingRight;
	}

	public void setBackgroundVisible(boolean backgroundVisible) {
		this.backgroundVisible = backgroundVisible;
	}

	public void setLocalizationService(LocalizationService localizationService) {
		this.localizationService = localizationService;
	}

	public void addOnClickListenerAfter(OnClickListener listener) {
		if(afterListeners == null) {
			afterListeners = new ArrayList<View.OnClickListener>(3);
		}
		afterListeners.add(listener);
	}

	public void addOnClickListenerBefore(OnClickListener listener) {
		if(beforeListeners == null) {
			beforeListeners = new ArrayList<View.OnClickListener>(3);
		}

		beforeListeners.add(listener);
	}

	@Override
	public void setEnabled(boolean enabled) {
		super.setEnabled(enabled);

		if(enabled) {
			textColor = Color.WHITE;
		}
		else {
			textColor = colors.getColor(Colors.BUTTON_DISABLED_TEXT);
		}

		if(textView != null) {
			textView.setTextColor(textColor);
		}
	}
}


/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.demo.implementations.twitter;

import android.app.Activity;
import com.socialize.api.SocializeSession;
import com.socialize.demo.SDKDemoActivity;
import com.socialize.error.SocializeException;
import com.socialize.listener.SocializeAuthListener;
import com.socialize.networks.SocialNetwork;
import com.socialize.networks.SocialNetworkPostListener;
import com.socialize.networks.twitter.TwitterUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * @author Jason Polites
 *
 */
public class UserTimelineActivity extends SDKDemoActivity {

	/* (non-Javadoc)
	 * @see com.socialize.demo.DemoActivity#executeDemo()
	 */
	@Override
	public void executeDemo(String text) {

		TwitterUtils.link(this, new SocializeAuthListener() {

			@Override
			public void onError(SocializeException error) {
				handleError(UserTimelineActivity.this, error);
			}

			@Override
			public void onCancel() {
				handleCancel();
			}

			@Override
			public void onAuthSuccess(SocializeSession session) {

				TwitterUtils.get(UserTimelineActivity.this, "statuses/user_timeline.json", null, new SocialNetworkPostListener() {

					@Override
					public void onNetworkError(Activity context, SocialNetwork network, Exception error) {
						handleError(context, error);
					}

					@Override
					public void onCancel() {
						handleCancel();
					}

					@Override
					public void onAfterPost(Activity parent, SocialNetwork socialNetwork, JSONObject responseObject) {

						try {
							JSONArray jsonArray = responseObject.getJSONArray("data");

							StringBuilder builder = new StringBuilder();

							int len = jsonArray.length();

							for (int i = 0; i < len; i++) {
								if(i > 0) {
									builder.append("\n");
								}
								builder.append(jsonArray.getString(i));
							}

							handleResult(builder.toString());
						}
						catch (JSONException e) {
							handleError(parent, e);
						}
					}
				});
			}

			@Override
			public void onAuthFail(SocializeException error) {
				handleError(UserTimelineActivity.this, error);
			}
		});
	}

	@Override
	public boolean isTextEntryRequired() {
		return false;
	}

	/* (non-Javadoc)
	 * @see com.socialize.demo.DemoActivity#getButtonText()
	 */
	@Override
	public String getButtonText() {
		return "Show My Timeline";
	}
}


package com.socialize.ui.profile;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.socialize.Socialize;
import com.socialize.UserUtils;
import com.socialize.error.SocializeException;
import com.socialize.log.SocializeLogger;
import com.socialize.ui.view.EntityView;

public class ProfileView extends EntityView {

	private ProfileLayoutView profileLayoutView = null;

	public ProfileView(Activity context) {
		super(context);
	}

	@Override
	protected View getView(Bundle bundle, Object...entityKeys) {
		if (entityKeys != null) {
			if(profileLayoutView == null) {
				profileLayoutView = container.getBean("profileLayoutView", entityKeys);
			}
			return profileLayoutView;
		}
		else {
			SocializeLogger.e("No user id specified for " + getClass().getSimpleName());
			return null;
		}
	}

	@Override
	protected String[] getBundleKeys() {
		return new String[]{Socialize.USER_ID};
	}

	/**
	 * Called when the user's profile image is changed.
	 * @param bitmap The image.
	 */
	public void onImageChange(Bitmap bitmap, String localPath) {
		if(profileLayoutView != null) {
			profileLayoutView.onImageChange(bitmap);
		}

		// Set the image in the user settings
		try {
			UserUtils.getUserSettings(getContext()).setLocalImagePath(localPath);
		}
		catch (SocializeException e) {
			Log.e(SocializeLogger.LOG_TAG, "Error getting user settings", e);
		}
	}

	@Override
	public View getLoadingView() {
		return null;
	}
}


/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.demo.implementations.entity;

import com.socialize.EntityUtils;
import com.socialize.EntityUtils.SortOrder;
import com.socialize.demo.SDKDemoActivity;
import com.socialize.entity.Entity;
import com.socialize.entity.ListResult;
import com.socialize.error.SocializeException;
import com.socialize.listener.entity.EntityListListener;

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

/**
 * @author Jason Polites
 *
 */
public class GetPopularEntitiesActivity extends SDKDemoActivity {

	/* (non-Javadoc)
	 * @see com.socialize.demo.DemoActivity#executeDemo()
	 */
	@Override
	public void executeDemo(String text) {

		EntityUtils.getEntities(this, 0, PAGE_SIZE, SortOrder.TOTAL_ACTIVITY, new EntityListListener() {

			@Override
			public void onList(ListResult<Entity> entities) {

				List<Entity> items = entities.getItems();
				Collection<String> strResults = new ArrayList<String>();
				for (Entity socializeAction : items) {
					strResults.add(socializeAction.toString() + " (Total Activity " + socializeAction.getEntityStats().getTotalActivityCount() + ")");
				}

				handleResults(strResults);
			}

			@Override
			public void onError(SocializeException error) {
				handleError(GetPopularEntitiesActivity.this, error);
			}
		});
	}

	@Override
	public boolean isTextEntryRequired() {
		return false;
	}

	/* (non-Javadoc)
	 * @see com.socialize.demo.DemoActivity#getButtonText()
	 */
	@Override
	public String getButtonText() {
		return "List top " + PAGE_SIZE + " most popular entities";
	}
}


/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.demo.implementations.entity;

import com.socialize.EntityUtils;
import com.socialize.demo.SDKDemoActivity;
import com.socialize.entity.Entity;
import com.socialize.error.SocializeException;
import com.socialize.listener.entity.EntityAddListener;

/**
 * @author Jason Polites
 *
 */
public class AddEntityActivity extends SDKDemoActivity {

	/* (non-Javadoc)
	 * @see com.socialize.demo.DemoActivity#executeDemo()
	 */
	@Override
	public void executeDemo(String text) {

		// usually the name parameter would be a human readable name (i.e. not the same as the key).
		Entity e = Entity.newInstance(text, text);

		EntityUtils.saveEntity(this, e, new EntityAddListener() {

			@Override
			public void onError(SocializeException error) {
				handleError(AddEntityActivity.this, error);
			}

			@Override
			public void onCreate(Entity entity) {
				handleBasicSocializeResult(entity);
			}
		});
	}

	@Override
	public boolean isTextEntryRequired() {
		return true;
	}

	/* (non-Javadoc)
	 * @see com.socialize.demo.DemoActivity#getButtonText()
	 */
	@Override
	public String getButtonText() {
		return "Add Entity";
	}
}


/*
 * Copyright (c) 2009 Matthias Kaeppler 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 com.socialize.oauth.signpost;

import com.socialize.oauth.signpost.exception.OAuthCommunicationException;
import com.socialize.oauth.signpost.exception.OAuthExpectationFailedException;
import com.socialize.oauth.signpost.exception.OAuthMessageSignerException;
import com.socialize.oauth.signpost.exception.OAuthNotAuthorizedException;
import com.socialize.oauth.signpost.http.HttpParameters;
import com.socialize.oauth.signpost.http.HttpRequest;
import com.socialize.oauth.signpost.http.HttpResponse;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * ABC for all provider implementations. If you're writing a custom provider,
 * you will probably inherit from this class, since it takes a lot of work from
 * you.
 *
 * @author Matthias Kaeppler
 */
public abstract class AbstractOAuthProvider implements OAuthProvider {

	private static final long serialVersionUID = 1L;

	private String requestTokenEndpointUrl;

	private String accessTokenEndpointUrl;

	private String authorizationWebsiteUrl;

	private HttpParameters responseParameters;

	private Map<String, String> defaultHeaders;

	private boolean isOAuth10a;

	private transient OAuthProviderListener listener;

	public AbstractOAuthProvider(String requestTokenEndpointUrl, String accessTokenEndpointUrl, String authorizationWebsiteUrl) {
		this.requestTokenEndpointUrl = requestTokenEndpointUrl;
		this.accessTokenEndpointUrl = accessTokenEndpointUrl;
		this.authorizationWebsiteUrl = authorizationWebsiteUrl;
		this.responseParameters = new HttpParameters();
		this.defaultHeaders = new HashMap<String, String>();
	}

	public String retrieveRequestToken(OAuthConsumer consumer, String callbackUrl) throws OAuthMessageSignerException, OAuthNotAuthorizedException, OAuthExpectationFailedException, OAuthCommunicationException {

		// invalidate current credentials, if any
		consumer.setTokenWithSecret(null, null);

		// 1.0a expects the callback to be sent while getting the request token.
		// 1.0 service providers would simply ignore this parameter.
		retrieveToken(consumer, requestTokenEndpointUrl, (OAuthTokenListener)null, OAuth.OAUTH_CALLBACK, callbackUrl);

		String callbackConfirmed = responseParameters.getFirst(OAuth.OAUTH_CALLBACK_CONFIRMED);
		responseParameters.remove(OAuth.OAUTH_CALLBACK_CONFIRMED);
		isOAuth10a = Boolean.TRUE.toString().equals(callbackConfirmed);

		// 1.0 service providers expect the callback as part of the auth URL,
		// Do not send when 1.0a.
		if (isOAuth10a) {
			return OAuth.addQueryParameters(authorizationWebsiteUrl, OAuth.OAUTH_TOKEN, consumer.getToken());
		} else {
			return OAuth.addQueryParameters(authorizationWebsiteUrl, OAuth.OAUTH_TOKEN, consumer.getToken(), OAuth.OAUTH_CALLBACK, callbackUrl);
		}
	}

	public void retrieveAccessToken(OAuthConsumer consumer, String oauthVerifier, OAuthTokenListener listener) throws OAuthMessageSignerException, OAuthNotAuthorizedException, OAuthExpectationFailedException, OAuthCommunicationException {

		if (consumer.getToken() == null || consumer.getTokenSecret() == null) {
			throw new OAuthExpectationFailedException("Authorized request token or token secret not set. " + "Did you retrieve an authorized request token before?");
		}

		if (isOAuth10a && oauthVerifier != null) {
			retrieveToken(consumer, accessTokenEndpointUrl, listener, OAuth.OAUTH_VERIFIER, oauthVerifier);
		} else {
			retrieveToken(consumer, accessTokenEndpointUrl, listener);
		}
	}

	/**
	 *

	 * Implemented by subclasses. The responsibility of this method is to
	 * contact the service provider at the given endpoint URL and fetch a
	 * request or access token. What kind of token is retrieved solely depends
	 * on the URL being used.
	 *

	 *

	 * Correct implementations of this method must guarantee the following
	 * post-conditions:
	 *

	 *
the {@link OAuthConsumer} passed to this method must have a valid
	 * {@link OAuth#OAUTH_TOKEN} and {@link OAuth#OAUTH_TOKEN_SECRET} set by
	 * calling {@link OAuthConsumer#setTokenWithSecret(String, String)}

	 *
{@link #getResponseParameters()} must return the set of query
	 * parameters served by the service provider in the token response, with all
	 * OAuth specific parameters being removed

	 *

	 *

	 *
	 * @param consumer
	 *            the {@link OAuthConsumer} that should be used to sign the
	 *            request
	 * @param endpointUrl
	 *            the URL at which the service provider serves the OAuth token
	 *            that is to be fetched
	 * @param additionalParameters
	 *            you can pass parameters here (typically OAuth parameters such
	 *            as oauth_callback or oauth_verifier) which will go directly
	 *            into the signer, i.e. you don't have to put them into the
	 *            request first, just so the consumer pull them out again. Pass
	 *            them sequentially in key/value order.
	 * @throws OAuthMessageSignerException
	 *             if signing the token request fails
	 * @throws OAuthCommunicationException
	 *             if a network communication error occurs
	 * @throws OAuthNotAuthorizedException
	 *             if the server replies 401 - Unauthorized
	 * @throws OAuthExpectationFailedException
	 *             if an expectation has failed, e.g. because the server didn't
	 *             reply in the expected format
	 */
	protected void retrieveToken(
			OAuthConsumer consumer,
			String endpointUrl,
			OAuthTokenListener listener,
			String... additionalParameters) throws OAuthMessageSignerException, OAuthCommunicationException, OAuthNotAuthorizedException, OAuthExpectationFailedException {
		Map<String, String> defaultHeaders = getRequestHeaders();

		if (consumer.getConsumerKey() == null || consumer.getConsumerSecret() == null) {
			throw new OAuthExpectationFailedException("Consumer key or secret not set");
		}

		HttpRequest request = null;
		HttpResponse response = null;
		try {
			request = createRequest(endpointUrl);
			for (String header : defaultHeaders.keySet()) {
				request.setHeader(header, defaultHeaders.get(header));
			}
			if (additionalParameters != null) {
				HttpParameters httpParams = new HttpParameters();
				httpParams.putAll(additionalParameters, true);
				consumer.setAdditionalParameters(httpParams);
			}

			if (this.listener != null) {
				this.listener.prepareRequest(request);
			}

			consumer.sign(request);

			if (this.listener != null) {
				this.listener.prepareSubmission(request);
			}

			response = sendRequest(request);
			int statusCode = response.getStatusCode();

			boolean requestHandled = false;
			if (this.listener != null) {
				requestHandled = this.listener.onResponseReceived(request, response);
			}
			if (requestHandled) {
				return;
			}

			if (statusCode >= 300) {
				handleUnexpectedResponse(statusCode, response);
			}

			HttpParameters responseParams = OAuth.decodeForm(response.getContent());

			if(listener != null) {
				listener.onResponse(responseParams);
			}

			String token = responseParams.getFirst(OAuth.OAUTH_TOKEN);
			String secret = responseParams.getFirst(OAuth.OAUTH_TOKEN_SECRET);
			responseParams.remove(OAuth.OAUTH_TOKEN);
			responseParams.remove(OAuth.OAUTH_TOKEN_SECRET);

			setResponseParameters(responseParams);

			if (token == null || secret == null) {
				throw new OAuthExpectationFailedException("Request token or token secret not set in server reply. " + "The service provider you use is probably buggy.");
			}

			consumer.setTokenWithSecret(token, secret);

		} catch (OAuthNotAuthorizedException e) {
			throw e;
		} catch (OAuthExpectationFailedException e) {
			throw e;
		} catch (Exception e) {
			throw new OAuthCommunicationException(e);
		} finally {
			try {
				closeConnection(request, response);
			} catch (Exception e) {
				throw new OAuthCommunicationException(e);
			}
		}
	}

	protected void handleUnexpectedResponse(int statusCode, HttpResponse response) throws Exception {
		if (response == null) {
			return;
		}
		BufferedReader reader = new BufferedReader(new InputStreamReader(response.getContent()));
		StringBuilder responseBody = new StringBuilder();

		String line = reader.readLine();
		while (line != null) {
			responseBody.append(line);
			line = reader.readLine();
		}

		switch (statusCode) {
		case 401:
			throw new OAuthNotAuthorizedException(responseBody.toString());
		default:
			throw new OAuthCommunicationException("Service provider responded in error: " + statusCode + " (" + response.getReasonPhrase() + ")", responseBody.toString());
		}
	}

	/**
	 * Overrride this method if you want to customize the logic for building a
	 * request object for the given endpoint URL.
	 *
	 * @param endpointUrl
	 *            the URL to which the request will go
	 * @return the request object
	 * @throws Exception
	 *             if something breaks
	 */
	protected abstract HttpRequest createRequest(String endpointUrl) throws Exception;

	/**
	 * Override this method if you want to customize the logic for how the given
	 * request is sent to the server.
	 *
	 * @param request
	 *            the request to send
	 * @return the response to the request
	 * @throws Exception
	 *             if something breaks
	 */
	protected abstract HttpResponse sendRequest(HttpRequest request) throws Exception;

	/**
	 * Called when the connection is being finalized after receiving the
	 * response. Use this to do any cleanup / resource freeing.
	 *
	 * @param request
	 *            the request that has been sent
	 * @param response
	 *            the response that has been received
	 * @throws Exception
	 *             if something breaks
	 */
	protected void closeConnection(HttpRequest request, HttpResponse response) throws Exception {
		// NOP
	}

	public HttpParameters getResponseParameters() {
		return responseParameters;
	}

	/**
	 * Returns a single query parameter as served by the service provider in a
	 * token reply. You must call {@link #setResponseParameters} with the set of
	 * parameters before using this method.
	 *
	 * @param key
	 *            the parameter name
	 * @return the parameter value
	 */
	protected String getResponseParameter(String key) {
		return responseParameters.getFirst(key);
	}

	public void setResponseParameters(HttpParameters parameters) {
		this.responseParameters = parameters;
	}

	public void setOAuth10a(boolean isOAuth10aProvider) {
		this.isOAuth10a = isOAuth10aProvider;
	}

	public boolean isOAuth10a() {
		return isOAuth10a;
	}

	public String getRequestTokenEndpointUrl() {
		return this.requestTokenEndpointUrl;
	}

	public String getAccessTokenEndpointUrl() {
		return this.accessTokenEndpointUrl;
	}

	public String getAuthorizationWebsiteUrl() {
		return this.authorizationWebsiteUrl;
	}

	public void setRequestHeader(String header, String value) {
		defaultHeaders.put(header, value);
	}

	public Map<String, String> getRequestHeaders() {
		return defaultHeaders;
	}

	public void setListener(OAuthProviderListener listener) {
		this.listener = listener;
	}

	public void removeListener(OAuthProviderListener listener) {
		this.listener = null;
	}
}


/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.demo.implementations.action;

import com.socialize.ActionUtils;
import com.socialize.demo.SDKDemoActivity;
import com.socialize.entity.ListResult;
import com.socialize.entity.SocializeAction;
import com.socialize.error.SocializeException;
import com.socialize.listener.activity.ActionListListener;

/**
 * @author Jason Polites
 *
 */
public class GetActionsByEntityActivity extends SDKDemoActivity {

	/* (non-Javadoc)
	 * @see com.socialize.demo.DemoActivity#executeDemo()
	 */
	@Override
	public void executeDemo(String text) {

		ActionUtils.getActionsByEntity(this, entity.getKey(), 0, PAGE_SIZE, new ActionListListener() {

			@Override
			public void onList(ListResult<SocializeAction> result) {
				handleSocializeResult(result);
			}

			@Override
			public void onError(SocializeException error) {
				handleError(GetActionsByEntityActivity.this, error);
			}
		});
	}

	@Override
	public boolean isTextEntryRequired() {
		return false;
	}

	/* (non-Javadoc)
	 * @see com.socialize.demo.DemoActivity#getButtonText()
	 */
	@Override
	public String getButtonText() {
		return "List " + PAGE_SIZE + " Actions for Current Entity";
	}
}


/*
 * Copyright (c) 2012 Socialize Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.socialize.ui.profile;

import android.content.Context;
import com.socialize.Socialize;
import com.socialize.SocializeService;
import com.socialize.UserUtils;
import com.socialize.listener.user.UserSaveListener;

/**
 * @author Jason Polites
 *
 */
public class DefaultProfileSaver implements ProfileSaver {

	/*
	 * (non-Javadoc)
	 * @see com.socialize.ui.profile.ProfileSaver#save(android.content.Context, java.lang.String, android.graphics.Bitmap, com.socialize.listener.user.UserSaveListener)
	 */
	@Override
	public void save(Context context, UserSettings profile, UserSaveListener listener) {
		UserUtils.saveUserSettings(context, profile, listener);
	}

	protected SocializeService getSocialize() {
		return Socialize.getSocialize();
	}
}


package com.socialize.util;

import com.socialize.Socialize;
import com.socialize.config.SocializeConfig;
import com.socialize.error.SocializeException;
import com.socialize.log.SocializeLogger;
import com.socialize.ui.SocializeEntityLoader;

public class SocializeEntityLoaderUtils implements EntityLoaderUtils {

	private SocializeConfig config;
	private ObjectUtils objectUtils;
	private SocializeLogger logger;

	/* (non-Javadoc)
	 * @see com.socialize.util.EntityLoaderUtils#initEntityLoader()
	 */
	@Override
	public SocializeEntityLoader initEntityLoader() {
		SocializeEntityLoader entityLoader = Socialize.getSocialize().getEntityLoader();

		if(entityLoader == null) {

			String entityLoaderClassName = config.getProperty(SocializeConfig.SOCIALIZE_ENTITY_LOADER);

			if(!StringUtils.isEmpty(entityLoaderClassName)) {
				try {
					if(logger != null && logger.isDebugEnabled()) {
						logger.debug("Instantiating entity loader [" +
								entityLoader +
								"]");
					}

					Object loader = objectUtils.construct(entityLoaderClassName);

					if(loader instanceof SocializeEntityLoader) {
						entityLoader = (SocializeEntityLoader)loader;

						Socialize.getSocialize().setEntityLoader(entityLoader);
					}
					else {
						if(logger != null) {
							logger.error("Entity loader [" +
									entityLoader +
									"] is not an instance of [" +
									SocializeEntityLoader.class.getName() +
									"]");
						}
					}
				}
				catch (SocializeException e) {
					if(logger != null) {
						logger.error("Failed to instantiate entity loader [" +
								entityLoader +
								"]", e);
					}
				}
			}
			else {
				if(logger != null) {
					logger.warn("No entity loader specified in socialize.properties");
				}
			}
		}

		return entityLoader;
	}

	public void setConfig(SocializeConfig config) {
		this.config = config;
	}

	public void setObjectUtils(ObjectUtils objectUtils) {
		this.objectUtils = objectUtils;
	}

	public void setLogger(SocializeLogger logger) {
		this.logger = logger;
	}

}