You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by ro...@apache.org on 2014/11/13 02:40:46 UTC
[3/6] incubator-usergrid git commit: Merged ported Apigee android sdk
to 1.0
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/21b60593/sdks/android/src/main/java/org/apache/usergrid/android/sdk/UGClient.java
----------------------------------------------------------------------
diff --git a/sdks/android/src/main/java/org/apache/usergrid/android/sdk/UGClient.java b/sdks/android/src/main/java/org/apache/usergrid/android/sdk/UGClient.java
new file mode 100755
index 0000000..61b069f
--- /dev/null
+++ b/sdks/android/src/main/java/org/apache/usergrid/android/sdk/UGClient.java
@@ -0,0 +1,3160 @@
+package org.apache.usergrid.android.sdk;
+
+import static org.apache.usergrid.android.sdk.utils.ObjectUtils.isEmpty;
+import static org.apache.usergrid.android.sdk.utils.UrlUtils.addQueryParams;
+import static org.apache.usergrid.android.sdk.utils.UrlUtils.encodeParams;
+import static org.apache.usergrid.android.sdk.utils.UrlUtils.path;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Date;
+
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationListener;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Log;
+
+import org.apache.usergrid.android.sdk.URLConnectionFactory;
+import org.apache.usergrid.android.sdk.callbacks.ApiResponseCallback;
+import org.apache.usergrid.android.sdk.callbacks.ClientAsyncTask;
+import org.apache.usergrid.android.sdk.callbacks.GroupsRetrievedCallback;
+import org.apache.usergrid.android.sdk.callbacks.QueryResultsCallback;
+import org.apache.usergrid.android.sdk.entities.Activity;
+import org.apache.usergrid.android.sdk.entities.Collection;
+import org.apache.usergrid.android.sdk.entities.Device;
+import org.apache.usergrid.android.sdk.entities.Entity;
+import org.apache.usergrid.android.sdk.entities.Group;
+import org.apache.usergrid.android.sdk.entities.Message;
+import org.apache.usergrid.android.sdk.entities.User;
+import org.apache.usergrid.android.sdk.response.ApiResponse;
+import org.apache.usergrid.android.sdk.utils.DeviceUuidFactory;
+import org.apache.usergrid.android.sdk.utils.JsonUtils;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+
+
+/**
+ * The UGClient class for accessing the Usergrid API. Start by instantiating this
+ * class though the appropriate constructor. Most calls to the API will be handled
+ * by the methods in this class.
+ *
+ * @see org.apache.usergrid.android.sdk.UGClient
+ * @see <a href="http://apigee.com/docs/app-services/content/installing-apigee-sdk-android">Usergrid SDK install guide</a>
+ */
+public class UGClient {
+
+ /**
+ * Most current version of the Usergrid Android SDK
+ */
+ public static final String SDK_VERSION = "0.0.8";
+ /**
+ * Platform type of this SDK
+ */
+ public static final String SDK_TYPE = "Android";
+
+ /**
+ * @y.exclude
+ */
+ public static final String OPTION_KEY_BASE_URL = "baseURL";
+
+ /**
+ * @y.exclude
+ */
+ public static boolean FORCE_PUBLIC_API = false;
+
+ /**
+ * Public API
+ */
+ public static String PUBLIC_API_URL = "https://api.usergrid.com";
+
+ /**
+ * Local API of standalone server
+ */
+ public static String LOCAL_STANDALONE_API_URL = "http://localhost:8080";
+
+ /**
+ * Local API of Tomcat server in Eclipse
+ */
+ public static String LOCAL_TOMCAT_API_URL = "http://localhost:8080/ROOT";
+
+ /**
+ * Local API
+ */
+ public static String LOCAL_API_URL = LOCAL_STANDALONE_API_URL;
+
+ /**
+ * Standard HTTP methods use in generic request methods
+ * @see apiRequest
+ * @see doHttpRequest
+ */
+ protected static final String HTTP_METHOD_DELETE = "DELETE";
+ /**
+ * Standard HTTP methods use in generic request methods
+ * @see apiRequest
+ * @see doHttpRequest
+ */
+ protected static final String HTTP_METHOD_GET = "GET";
+ /**
+ * Standard HTTP methods use in generic request methods
+ * @see apiRequest
+ * @see doHttpRequest
+ */
+ protected static final String HTTP_METHOD_POST = "POST";
+ /**
+ * Standard HTTP methods use in generic request methods
+ * @see apiRequest
+ * @see doHttpRequest
+ */
+ protected static final String HTTP_METHOD_PUT = "PUT";
+
+ protected static final String LOGGING_TAG = "UGCLIENT";
+
+ private String apiUrl = PUBLIC_API_URL;
+
+ private String organizationId;
+ private String applicationId;
+ private String clientId;
+ private String clientSecret;
+
+ private User loggedInUser = null;
+
+ private String accessToken = null;
+
+ private String currentOrganization = null;
+ private URLConnectionFactory urlConnectionFactory = null;
+
+ private LocationManager locationManager;
+ private UUID deviceID;
+
+ /**
+ * Interface for EntityQuery and QueueQuery
+ */
+ public interface Query {
+
+ public ApiResponse getResponse();
+
+ public boolean more();
+
+ public Query next();
+
+ }
+
+ /**
+ * @y.exclude
+ */
+ public static boolean isUuidValid(UUID uuid) {
+ return( uuid != null );
+ }
+
+ protected static String arrayToDelimitedString(String[] arrayOfStrings, String delimiter) {
+ StringBuilder sb = new StringBuilder();
+
+ for( int i = 0; i < arrayOfStrings.length; ++i ) {
+ if( i > 0 ) {
+ sb.append(delimiter);
+ }
+
+ sb.append(arrayOfStrings[i]);
+ }
+
+ return sb.toString();
+ }
+
+ protected static String[] tokenizeToStringArray(String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) {
+ if (str == null) {
+ return null;
+ }
+
+ StringTokenizer st = new StringTokenizer(str, delimiters);
+
+ int numTokens = st.countTokens();
+ List<String> listTokens;
+
+ if( numTokens > 0 ) {
+
+ listTokens = new ArrayList<String>(numTokens);
+
+ while (st.hasMoreTokens()) {
+
+ String token = st.nextToken();
+
+ if (trimTokens) {
+ token = token.trim();
+ }
+
+ if (!ignoreEmptyTokens || token.length() > 0) {
+ listTokens.add(token);
+ }
+ }
+ } else {
+ listTokens = new ArrayList<String>();
+ }
+
+ return listTokens.toArray(new String[listTokens.size()]);
+ }
+
+
+ /****************** CONSTRUCTORS ***********************/
+ /****************** CONSTRUCTORS ***********************/
+
+ /**
+ * @y.exclude
+ */
+ public UGClient() {
+ init();
+ }
+
+ /**
+ * Instantiate a data client for a specific app. This is used to call most
+ * SDK methods.
+ *
+ * @param organizationId the Usergrid organization name
+ * @param applicationId the Usergrid application id or name
+ */
+ public UGClient(String organizationId, String applicationId) {
+ init();
+ this.organizationId = organizationId;
+ this.applicationId = applicationId;
+ }
+
+ /**
+ * Instantiate a data client for a specific app with a base URL other than the default
+ * api.usergrid.com. This is used to call most SDK methods.
+ *
+ * @param organizationId the Usergrid organization name
+ * @param applicationId the Usergrid application id or name
+ * @param baseURL the base URL to use for all API calls
+ */
+ public UGClient(String organizationId, String applicationId, String baseURL) {
+ init();
+ this.organizationId = organizationId;
+ this.applicationId = applicationId;
+
+ if( baseURL != null ) {
+ this.setApiUrl(baseURL);
+ }
+ }
+
+ public void init() {
+ }
+
+
+ /****************** ACCESSORS/MUTATORS ***********************/
+ /****************** ACCESSORS/MUTATORS ***********************/
+
+ /**
+ * Sets a new URLConnectionFactory object in the UGClient
+ *
+ * @param urlConnectionFactory a new URLConnectionFactory object
+ * @y.exclude
+ */
+ public void setUrlConnectionFactory(URLConnectionFactory urlConnectionFactory) {
+ this.urlConnectionFactory = urlConnectionFactory;
+ }
+
+ /**
+ * @return the Usergrid API url (default: http://api.usergrid.com)
+ */
+ public String getApiUrl() {
+ return apiUrl;
+ }
+
+ /**
+ * Sets the base URL for API requests
+ *
+ * @param apiUrl the API base url to be set (default: http://api.usergrid.com)
+ */
+ public void setApiUrl(String apiUrl) {
+ this.apiUrl = apiUrl;
+ }
+
+ /**
+ * Sets the base URL for API requests and returns the updated UGClient object
+ *
+ * @param apiUrl the Usergrid API url (default: http://api.usergrid.com)
+ * @return UGClient object for method call chaining
+ */
+ public UGClient withApiUrl(String apiUrl) {
+ this.apiUrl = apiUrl;
+ return this;
+ }
+
+
+ /**
+ * Sets the Usergrid organization ID and returns the UGClient object
+ *
+ * @param organizationId the organizationId to set
+ * @return the updated UGClient object
+ */
+ public UGClient withOrganizationId(String organizationId){
+ this.organizationId = organizationId;
+ return this;
+ }
+
+
+
+ /**
+ * Gets the current Usergrid organization ID set in the UGClient
+ *
+ * @return the current organizationId
+ */
+ public String getOrganizationId() {
+ return organizationId;
+ }
+
+ /**
+ * Sets the Usergrid organization ID
+ *
+ * @param organizationId the organizationId to set
+ */
+ public void setOrganizationId(String organizationId) {
+ this.organizationId = organizationId;
+ }
+
+ /**
+ * Gets the current Usergrid application ID set in the UGClient
+ *
+ * @return the current organizationId or name
+ */
+ public String getApplicationId() {
+ return applicationId;
+ }
+
+ /**
+ * Sets the Usergrid application Id
+ *
+ * @param applicationId the application id or name
+ */
+ public void setApplicationId(String applicationId) {
+ this.applicationId = applicationId;
+ }
+
+
+ /**
+ * Sets the Usergrid application ID and returns the UGClient object
+ *
+ * @param applicationId the application ID to set
+ * @return the updated UGClient object
+ */
+ public UGClient withApplicationId(String applicationId) {
+ this.applicationId = applicationId;
+ return this;
+ }
+
+ /**
+ * Gets the application (not organization) client ID credential for making calls as the
+ * application-owner. Not safe for most mobile use.
+ * @return the client id
+ */
+ public String getClientId() {
+ return clientId;
+ }
+
+ /**
+ * Sets the application (not organization) client ID credential, used for making
+ * calls as the application-owner. Not safe for most mobile use.
+ * @param clientId the client id
+ */
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ /**
+ * Sets the client ID credential in the UGClient object. Not safe for most mobile use.
+ *
+ * @param clientId the client key id
+ * @return UGClient object for method call chaining
+ */
+ public UGClient withClientId(String clientId) {
+ this.clientId = clientId;
+ return this;
+ }
+
+ /**
+ * Gets the application (not organization) client secret credential for making calls as the
+ * application-owner. Not safe for most mobile use.
+ * @return the client secret
+ */
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ /**
+ * Sets the application (not organization) client secret credential, used for making
+ * calls as the application-owner. Not safe for most mobile use.
+ *
+ * @param clientSecret the client secret
+ */
+ public void setClientSecret(String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ /**
+ * Sets the client secret credential in the UGClient object. Not safe for most mobile use.
+ *
+ * @param clientSecret the client secret
+ * @return UGClient object for method call chaining
+ */
+ public UGClient withClientSecret(String clientSecret) {
+ this.clientSecret = clientSecret;
+ return this;
+ }
+
+ /**
+ * Gets the UUID of the logged-in user after a successful authorizeAppUser request
+ * @return the UUID of the logged-in user
+ */
+ public User getLoggedInUser() {
+ return loggedInUser;
+ }
+
+ /**
+ * Sets the UUID of the logged-in user. Usually not set by host application
+ * @param loggedInUser the UUID of the logged-in user
+ */
+ public void setLoggedInUser(User loggedInUser) {
+ this.loggedInUser = loggedInUser;
+ }
+
+ /**
+ * Gets the OAuth2 access token for the current logged-in user after a
+ * successful authorize request
+ *
+ * @return the OAuth2 access token
+ */
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ /**
+ * Saves the OAuth2 access token in the UGClient after a successful authorize
+ * request. Usually not set by host application.
+ *
+ * @param accessToken an OAuth2 access token
+ */
+ public void setAccessToken(String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ /**
+ * Gets the current organization from UGClient
+ *
+ * @return the currentOrganization
+ */
+ public String getCurrentOrganization() {
+ return currentOrganization;
+ }
+
+ /**
+ * Sets the current organizanization from UGClient
+ *
+ * @param currentOrganization The organization this data client should use.
+ */
+ public void setCurrentOrganization(String currentOrganization) {
+ this.currentOrganization = currentOrganization;
+ }
+
+ /****************** LOGGING ***********************/
+ /****************** LOGGING ***********************/
+
+
+ /**
+ * Logs a trace-level logging message with tag 'DATA_CLIENT'
+ *
+ * @param logMessage the message to log
+ */
+ public void logTrace(String logMessage) {
+ if( logMessage != null ) {
+ Log.v(LOGGING_TAG,logMessage);
+ }
+ }
+
+ /**
+ * Logs a debug-level logging message with tag 'DATA_CLIENT'
+ *
+ * @param logMessage the message to log
+ */
+ public void logDebug(String logMessage) {
+ if( logMessage != null ) {
+ Log.d(LOGGING_TAG,logMessage);
+ }
+ }
+
+ /**
+ * Logs an info-level logging message with tag 'DATA_CLIENT'
+ *
+ * @param logMessage the message to log
+ */
+ public void logInfo(String logMessage) {
+ if( logMessage != null ) {
+ Log.i(LOGGING_TAG,logMessage);
+ }
+ }
+
+ /**
+ * Logs a warn-level logging message with tag 'DATA_CLIENT'
+ *
+ * @param logMessage the message to log
+ */
+ public void logWarn(String logMessage) {
+ if( logMessage != null ) {
+ Log.w(LOGGING_TAG,logMessage);
+ }
+ }
+
+ /**
+ * Logs an error-level logging message with tag 'DATA_CLIENT'
+ *
+ * @param logMessage the message to log
+ */
+ public void logError(String logMessage) {
+ if( logMessage != null ) {
+ Log.e(LOGGING_TAG,logMessage);
+ }
+ }
+
+ /**
+ * Logs a debug-level logging message with tag 'DATA_CLIENT'
+ *
+ * @param logMessage the message to log
+ */
+ public void writeLog(String logMessage) {
+ if( logMessage != null ) {
+ //TODO: do we support different log levels in this class?
+ Log.d(LOGGING_TAG, logMessage);
+ }
+ }
+
+ /****************** API/HTTP REQUEST ***********************/
+ /****************** API/HTTP REQUEST ***********************/
+
+ /**
+ * Forms and initiates a raw synchronous http request and processes the response.
+ *
+ * @param httpMethod the HTTP method in the format:
+ * HTTP_METHOD_<method_name> (e.g. HTTP_METHOD_POST)
+ * @param params the URL parameters to append to the request URL
+ * @param data the body of the request
+ * @param segments additional URL path segments to append to the request URL
+ * @return ApiResponse object
+ */
+ public ApiResponse doHttpRequest(String httpMethod, Map<String, Object> params, Object data, String... segments) {
+
+ ApiResponse response = null;
+ OutputStream out = null;
+ InputStream in = null;
+ HttpURLConnection conn = null;
+
+ String urlAsString = path(apiUrl, segments);
+
+ try {
+ String contentType = "application/json";
+ if (httpMethod.equals(HTTP_METHOD_POST) && isEmpty(data) && !isEmpty(params)) {
+ data = encodeParams(params);
+ contentType = "application/x-www-form-urlencoded";
+ } else {
+ urlAsString = addQueryParams(urlAsString, params);
+ }
+
+ //logTrace("Invoking " + httpMethod + " to '" + urlAsString + "'");
+
+ URL url = new URL(urlAsString);
+ conn = (HttpURLConnection) url.openConnection();
+
+ conn.setRequestMethod(httpMethod);
+ conn.setRequestProperty("Content-Type", contentType);
+ conn.setUseCaches(false);
+
+ if ((accessToken != null) && (accessToken.length() > 0)) {
+ String authStr = "Bearer " + accessToken;
+ conn.setRequestProperty("Authorization", authStr);
+ }
+
+ conn.setDoInput(true);
+
+ if (httpMethod.equals(HTTP_METHOD_POST) || httpMethod.equals(HTTP_METHOD_PUT)) {
+ if (isEmpty(data)) {
+ data = JsonNodeFactory.instance.objectNode();
+ }
+
+ String dataAsString = null;
+
+ if ((data != null) && (!(data instanceof String))) {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ dataAsString = objectMapper.writeValueAsString(data);
+ } else {
+ dataAsString = (String) data;
+ }
+
+ //logTrace("Posting/putting data: '" + dataAsString + "'");
+
+ byte[] dataAsBytes = dataAsString.getBytes();
+
+ conn.setRequestProperty("Content-Length", Integer.toString(dataAsBytes.length));
+ conn.setDoOutput(true);
+
+ out = conn.getOutputStream();
+ out.write(dataAsBytes);
+ out.flush();
+ out.close();
+ out = null;
+ }
+
+ in = conn.getInputStream();
+ if( in != null ) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ StringBuilder sb = new StringBuilder();
+ String line;
+
+ while( (line = reader.readLine()) != null ) {
+ sb.append(line);
+ sb.append('\n');
+ }
+
+ String responseAsString = sb.toString();
+
+ //logTrace("response from server: '" + responseAsString + "'");
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ response = (ApiResponse) objectMapper.readValue(responseAsString, ApiResponse.class);
+ response.setRawResponse(responseAsString);
+
+ response.setUGClient(this);
+ } else {
+ response = null;
+ logTrace("no response body from server");
+ }
+
+ //final int responseCode = conn.getResponseCode();
+ //logTrace("responseCode from server = " + responseCode);
+ }
+ catch(Exception e) {
+ logError("Error " + httpMethod + " to '" + urlAsString + "'" );
+ if( e != null ) {
+ e.printStackTrace();
+ logError(e.getLocalizedMessage());
+ }
+ response = null;
+ }
+ catch(Throwable t) {
+ logError("Error " + httpMethod + " to '" + urlAsString + "'" );
+ if( t != null ) {
+ t.printStackTrace();
+ logError(t.getLocalizedMessage());
+ }
+ response = null;
+ }
+ finally {
+ try {
+ if( out != null ) {
+ out.close();
+ }
+
+ if( in != null ) {
+ in.close();
+ }
+
+ if( conn != null ) {
+ conn.disconnect();
+ }
+ } catch(Exception ignored) {
+ }
+ }
+
+ return response;
+ }
+
+
+ /**
+ * High-level synchronous API request. Implements the http request
+ * for most SDK methods by calling
+ * {@link #doHttpRequest(String,Map,Object,String...)}
+ *
+ * @param httpMethod the HTTP method in the format:
+ * HTTP_METHOD_<method_name> (e.g. HTTP_METHOD_POST)
+ * @param params the URL parameters to append to the request URL
+ * @param data the body of the request
+ * @param segments additional URL path segments to append to the request URL
+ * @return ApiResponse object
+ */
+ public ApiResponse apiRequest(String httpMethod,
+ Map<String, Object> params, Object data, String... segments) {
+ ApiResponse response = null;
+
+ response = doHttpRequest(httpMethod, params, data, segments);
+
+ if( (response == null) ) {
+ logError("doHttpRequest returned null");
+ }
+
+ return response;
+ }
+
+ protected void assertValidApplicationId() {
+ if (isEmpty(applicationId)) {
+ throw new IllegalArgumentException("No application id specified");
+ }
+ }
+
+ /****************** ROLES/PERMISSIONS ***********************/
+ /****************** ROLES/PERMISSIONS ***********************/
+
+ /**
+ * Assigns permissions to the specified user, group, or role.
+ *
+ * @param entityType the entity type of the entity the permissions are being assigned to. 'user', 'group' and 'role' are valid.
+ * @param entityID the UUID of 'name' property of the entity the permissions are being assigned to.
+ * @param permissions a comma-separated list of the permissions to be assigned in the format: <operations>:<path>, e.g. get, put, post, delete: /users
+ * @throws IllegalArgumentException thrown if an entityType other than 'group' or 'user' is passed to the method
+ * @return ApiResponse object
+ */
+ public ApiResponse assignPermissions(String entityType, String entityID, String permissions) {
+
+ if (!entityType.substring(entityType.length() - 1 ).equals("s")) {
+ entityType += "s";
+ }
+
+ if (!validateTypeForPermissionsAndRoles(entityType, "permission")) {
+ throw new IllegalArgumentException("Permissions can only be assigned to group, user, or role entities");
+ }
+
+ Map<String, Object> data = new HashMap<String, Object>();
+ if (permissions != null){
+ data.put("permission", permissions);
+ }
+
+ return apiRequest(HTTP_METHOD_POST, null, data, organizationId, applicationId, entityType,
+ entityID, "permissions");
+
+ }
+
+ /**
+ * Assigns permissions to the specified user, group, or role. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param entityType the entity type of the entity the permissions are being assigned to. 'user', 'group' and 'role' are valid.
+ * @param entityID the UUID of 'name' property of the entity the permissions are being assigned to.
+ * @param permissions a comma-separated list of the permissions to be assigned in the format: <operations>:<path>, e.g. get, put, post, delete: /users
+ * @param callback an ApiResponseCallback to handle the async response
+ */
+ public void assignPermissionsAsync(final String entityType,
+ final String entityID, final String permissions, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return assignPermissions(entityType, entityID, permissions);
+ }
+ }).execute();
+ }
+
+ /**
+ * Removes permissions from the specified user, group or role.
+ *
+ * @param entityType the entity type of the entity the permissions are being removed from. 'user', 'group' and 'role' are valid.
+ * @param entityID the UUID of 'name' property of the entity the permissions are being removed from.
+ * @param permissions a comma-separated list of the permissions to be removed in the format: <operations>:<path>, e.g. get, put, post, delete: /users
+ * @throws IllegalArgumentException thrown if an entityType other than 'group' or 'user' is passed to the method
+ * @return ApiResponse object
+ */
+ public ApiResponse removePermissions(String entityType, String entityID, String permissions) {
+
+ if (!validateTypeForPermissionsAndRoles(entityType, "permission")) {
+ throw new IllegalArgumentException("Permissions can only be assigned to group, user, or role entities");
+ }
+
+ Map<String, Object> params = new HashMap<String, Object>();
+ if (permissions != null){
+ params.put("permission", permissions);
+ }
+
+ return apiRequest(HTTP_METHOD_DELETE, params, null, organizationId, applicationId, entityType,
+ entityID, "permissions");
+
+ }
+
+ /**
+ * Removes permissions from the specified user, group or role. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param entityType the entity type of the entity the permissions are being removed from. 'user', 'group', and 'role' are valid.
+ * @param entityID the UUID of 'name' property of the entity the permissions are being removed from.
+ * @param permissions a comma-separated list of the permissions to be removed in the format: <operations>:<path>, e.g. get, put, post, delete: /users
+ * @param callback an ApiResponseCallback to handle the async response
+ */
+ public void removePermissionsAsync(final String entityType,
+ final String entityID, final String permissions, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return removePermissions(entityType, entityID, permissions);
+ }
+ }).execute();
+ }
+
+ /**
+ * Creates a new role and assigns permissions to it.
+ *
+ * @param roleName the name of the new role
+ * @param permissions a comma-separated list of the permissions to be assigned in the format: <operations>:<path>, e.g. get, put, post, delete: /users
+ * @return ApiResponse object
+ */
+ public ApiResponse createRole(String roleName, String permissions) {
+
+ Map<String, Object> properties = new HashMap<String, Object>();
+ properties.put("type", "role");
+ properties.put("name", roleName);
+
+ ApiResponse response = this.createEntity(properties);
+
+ String uuid = null;
+
+ if (response.getEntityCount() == 1){
+ uuid = response.getFirstEntity().getUuid().toString();
+ }
+
+ return assignPermissions("role", uuid, permissions);
+
+ }
+
+ /**
+ * Creates a new role and assigns permissions to it.
+ *
+ * @param roleName the name of the new role
+ * @param permissions a comma-separated list of the permissions to be assigned in the format: <operations>:<path>, e.g. get, put, post, delete: /users
+ * @param callback an ApiResponseCallback to handle the async response
+ */
+ public void createRoleAsync(final String roleName, final String permissions,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return createRole(roleName, permissions);
+ }
+ }).execute();
+ }
+
+ /**
+ * Assigns a role to a user or group entity.
+ *
+ * @param roleName the name of the role to be assigned to the entity
+ * @param entityType the entity type of the entity the role is being assigned to. 'user' and 'group' are valid.
+ * @param entityID the UUID or 'name' property of the entity the role is being assigned to.
+ * @throws IllegalArgumentException thrown if an entityType other than 'group' or 'user' is passed to the method
+ * @return ApiResponse object
+ */
+ public ApiResponse assignRole(String roleName, String entityType, String entityID) {
+
+ if (!entityType.substring(entityType.length() - 1 ).equals("s")) {
+ entityType += "s";
+ }
+
+ if (!validateTypeForPermissionsAndRoles(entityType, "role")) {
+ throw new IllegalArgumentException("Permissions can only be assigned to a group or user");
+ }
+
+ return apiRequest(HTTP_METHOD_POST, null, null, organizationId, applicationId, "roles", roleName,
+ entityType, entityID);
+
+ }
+
+ /**
+ * Assigns a role to a user or group entity. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param roleName the name of the role to be assigned to the entity
+ * @param entityType the entity type of the entity the role is being assigned to. 'user' and 'group' are valid.
+ * @param entityID the UUID or 'name' property of the entity the role is being removed from.
+ * @param callback an ApiResponseCallback to handle the async response
+ */
+ public void assignRoleAsync(final String roleName, final String entityType,
+ final String entityID, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return assignRole(roleName, entityType, entityID);
+ }
+ }).execute();
+ }
+
+ /**
+ * Removes a role from a user or group entity.
+ *
+ * @param roleName the name of the role to be removed from the entity
+ * @param entityType the entity type of the entity the role is being removed from. 'user' and 'group' are valid.
+ * @param entityID the UUID or 'name' property of the entity the role is being removed from.
+ * @throws IllegalArgumentException thrown if an entityType other than 'group' or 'user' is passed to the method
+ * @return ApiResponse object
+ */
+ public ApiResponse removeRole(String roleName, String entityType, String entityID) {
+
+ if (!entityType.substring(entityType.length() - 1 ).equals("s")) {
+ entityType += "s";
+ }
+
+ if (!validateTypeForPermissionsAndRoles(entityType, "role")) {
+ throw new IllegalArgumentException("Permissions can only be removed from a group or user");
+ }
+
+ return apiRequest(HTTP_METHOD_DELETE, null, null, organizationId, applicationId, "roles", roleName,
+ entityType, entityID);
+
+ }
+
+ /**
+ * Removes a role from a user or group entity. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param roleName the name of the role to be removed from the entity
+ * @param entityType the entity type of the entity the role is being removed from. 'user' and 'group' are valid.
+ * @param entityID the UUID or 'name' property of the entity the role is being removed from.
+ * @param callback an ApiResponseCallback to handle the async response
+ */
+ public void removeRoleAsync(final String roleName, final String entityType,
+ final String entityID, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return removeRole(roleName, entityType, entityID);
+ }
+ }).execute();
+ }
+
+ /**
+ * Checks if a permission or role can be assigned to an entity
+ * @y.exclude
+ */
+ private Boolean validateTypeForPermissionsAndRoles(String type, String permissionOrRole){
+ ArrayList<String> validTypes = new ArrayList<String>();
+ validTypes.add("groups");
+ validTypes.add("users");
+
+ if (permissionOrRole.equals("permission")){
+ validTypes.add("roles");
+ }
+
+ return validTypes.contains(type);
+ }
+
+ /****************** LOG IN/LOG OUT/OAUTH ***********************/
+ /****************** LOG IN/LOG OUT/OAUTH ***********************/
+
+ /**
+ * Logs the user in and get a valid access token.
+ *
+ * @param usernameOrEmail the username or email associated with the user entity in Usergrid
+ * @param password the user's Usergrid password
+ * @return non-null ApiResponse if request succeeds, check getError() for
+ * "invalid_grant" to see if access is denied.
+ */
+ public ApiResponse authorizeAppUser(String usernameOrEmail, String password) {
+ validateNonEmptyParam(usernameOrEmail, "email");
+ validateNonEmptyParam(password,"password");
+ assertValidApplicationId();
+ loggedInUser = null;
+ accessToken = null;
+ currentOrganization = null;
+ Map<String, Object> formData = new HashMap<String, Object>();
+ formData.put("grant_type", "password");
+ formData.put("username", usernameOrEmail);
+ formData.put("password", password);
+ ApiResponse response = apiRequest(HTTP_METHOD_POST, formData, null,
+ organizationId, applicationId, "token");
+ if (response == null) {
+ return response;
+ }
+ if (!isEmpty(response.getAccessToken()) && (response.getUser() != null)) {
+ loggedInUser = response.getUser();
+ accessToken = response.getAccessToken();
+ currentOrganization = null;
+ logInfo("authorizeAppUser(): Access token: " + accessToken);
+ } else {
+ logInfo("authorizeAppUser(): Response: " + response);
+ }
+ return response;
+ }
+
+ /**
+ * Log the user in and get a valid access token. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param usernameOrEmail the username or email associated with the user entity in Usergrid
+ * @param password the users Usergrid password
+ * @param callback an ApiResponseCallback to handle the async response
+ */
+ public void authorizeAppUserAsync(final String usernameOrEmail,
+ final String password, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return authorizeAppUser(usernameOrEmail, password);
+ }
+ }).execute();
+ }
+
+ /**
+ * Change the password for the currently logged in user. You must supply the
+ * old password and the new password.
+ *
+ * @param username the username or email address associated with the user entity in Usergrid
+ * @param oldPassword the user's old password
+ * @param newPassword the user's new password
+ * @return ApiResponse object
+ */
+ public ApiResponse changePassword(String username, String oldPassword,
+ String newPassword) {
+
+ Map<String, Object> data = new HashMap<String, Object>();
+ data.put("newpassword", newPassword);
+ data.put("oldpassword", oldPassword);
+
+ return apiRequest(HTTP_METHOD_POST, null, data, organizationId, applicationId, "users",
+ username, "password");
+
+ }
+
+ public void changePasswordAsync(final String username, final String oldPassword,
+ final String newPassword, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return changePassword(username, oldPassword, newPassword);
+ }
+ }).execute();
+ }
+
+ /**
+ * Log the user in with their numeric pin-code and get a valid access token.
+ *
+ * @param email the email address associated with the user entity in Usergrid
+ * @param pin the pin associated with the user entity in Usergrid
+ * @return non-null ApiResponse if request succeeds, check getError() for
+ * "invalid_grant" to see if access is denied.
+ */
+ public ApiResponse authorizeAppUserViaPin(String email, String pin) {
+ validateNonEmptyParam(email, "email");
+ validateNonEmptyParam(pin, "pin");
+ assertValidApplicationId();
+ loggedInUser = null;
+ accessToken = null;
+ currentOrganization = null;
+ Map<String, Object> formData = new HashMap<String, Object>();
+ formData.put("grant_type", "pin");
+ formData.put("username", email);
+ formData.put("pin", pin);
+ ApiResponse response = apiRequest(HTTP_METHOD_POST, formData, null,
+ organizationId, applicationId, "token");
+ if (response == null) {
+ return response;
+ }
+ if (!isEmpty(response.getAccessToken()) && (response.getUser() != null)) {
+ loggedInUser = response.getUser();
+ accessToken = response.getAccessToken();
+ currentOrganization = null;
+ logInfo("authorizeAppUser(): Access token: " + accessToken);
+ } else {
+ logInfo("authorizeAppUser(): Response: " + response);
+ }
+ return response;
+ }
+
+ /**
+ * Log the user in with their numeric pin-code and get a valid access token.
+ * Executes asynchronously in background and the callbacks are called in the
+ * UI thread.
+ *
+ * @param email the email address associated with the user entity in Usergrid
+ * @param pin the pin associated with the user entity in Usergrid
+ * @param callback A callback for the async response.
+ */
+ public void authorizeAppUserViaPinAsync(final String email,
+ final String pin, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return authorizeAppUserViaPin(email, pin);
+ }
+ }).execute();
+ }
+
+ /**
+ * Log the app in with it's application (not organization) client id and
+ * client secret key. Not recommended for production apps. Executes asynchronously
+ * in background and the callbacks are called in the UI thread.
+ *
+ * @param clientId the Usergrid application's client ID
+ * @param clientSecret the Usergrid application's client secret
+ * @param callback an ApiResponseCallback to handle the async response
+ */
+ public void authorizeAppClientAsync(final String clientId,
+ final String clientSecret, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+
+ @Override
+ public ApiResponse doTask() {
+ return authorizeAppClient(clientId, clientSecret);
+ }
+ }).execute();
+ }
+
+ private void validateNonEmptyParam(Object param, String paramName) {
+ if ( isEmpty(param) ) {
+ throw new IllegalArgumentException(paramName + " cannot be null or empty");
+ }
+ }
+
+ /**
+ * Log the user in with their Facebook access token retrieved via Facebook
+ * OAuth. Sets the user's identifier and Usergrid OAuth2 access token in UGClient
+ * if successfully authorized.
+ *
+ * @param fb_access_token the valid OAuth token returned by Facebook
+ * @return non-null ApiResponse if request succeeds, check getError() for
+ * "invalid_grant" to see if access is denied.
+ */
+ public ApiResponse authorizeAppUserViaFacebook(String fb_access_token) {
+ validateNonEmptyParam(fb_access_token, "Facebook token");
+ assertValidApplicationId();
+ loggedInUser = null;
+ accessToken = null;
+ currentOrganization = null;
+ Map<String, Object> formData = new HashMap<String, Object>();
+ formData.put("fb_access_token", fb_access_token);
+ ApiResponse response = apiRequest(HTTP_METHOD_POST, formData, null,
+ organizationId, applicationId, "auth", "facebook");
+ if (response == null) {
+ return response;
+ }
+ if (!isEmpty(response.getAccessToken()) && (response.getUser() != null)) {
+ loggedInUser = response.getUser();
+ accessToken = response.getAccessToken();
+ currentOrganization = null;
+ logInfo("authorizeAppUserViaFacebook(): Access token: "
+ + accessToken);
+ } else {
+ logInfo("authorizeAppUserViaFacebook(): Response: "
+ + response);
+ }
+ return response;
+ }
+
+ /**
+ * Log the user in with their Facebook access token retrieved via Facebook
+ * OAuth. Sets the user's identifier and Usergrid OAuth2 access token in UGClient
+ * if successfully authorized. Executes asynchronously in background and the
+ * callbacks are called in the UI thread.
+ *
+ * @param fb_access_token the valid OAuth token returned by Facebook
+ * @param callback an ApiResponseCallback to handle the async response
+ */
+ public void authorizeAppUserViaFacebookAsync(final String fb_access_token,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return authorizeAppUserViaFacebook(fb_access_token);
+ }
+ }).execute();
+ }
+
+ /**
+ * Log out a user and destroy the access token currently stored in UGClient
+ * on the server and in the UGClient.
+ *
+ * @param username The username to be logged out
+ * @return non-null ApiResponse if request succeeds
+ */
+ public ApiResponse logOutAppUser(String username) {
+ String token = getAccessToken();
+ Map<String,Object> params = new HashMap<String,Object>();
+ params.put("token",token);
+ ApiResponse response = apiRequest(HTTP_METHOD_PUT, params, null,
+ organizationId, applicationId, "users",username,"revoketoken?");
+ if (response == null) {
+ return response;
+ } else {
+ logInfo("logoutAppUser(): Response: " + response);
+ setAccessToken(null);
+ }
+ return response;
+ }
+
+ /**
+ * Log out a user and destroy the access token currently stored in UGClient
+ * on the server and in the UGClient.
+ * Executes asynchronously in background and the callbacks are called in the
+ * UI thread.
+ *
+ * @param username The username to be logged out
+ * @param callback an ApiResponseCallback to handle the async response
+ */
+ public void logOutAppUserAsync(final String username, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return logOutAppUser(username);
+ }
+ }).execute();
+ }
+
+ /**
+ * Destroy a specific user token on the server. The token will also be cleared
+ * from the UGClient instance, if it matches the token provided.
+ *
+ * @param username The username to be logged out
+ * @param token The access token to be destroyed on the server
+ * @return non-null ApiResponse if request succeeds
+ */
+ public ApiResponse logOutAppUserForToken(String username, String token) {
+ Map<String,Object> params = new HashMap<String,Object>();
+ params.put("token",token);
+ ApiResponse response = apiRequest(HTTP_METHOD_PUT, params, null,
+ organizationId, applicationId, "users",username,"revoketoken?");
+ if (response == null) {
+ return response;
+ } else {
+ logInfo("logoutAppWithTokenUser(): Response: " + response);
+ if (token.equals(getAccessToken())) {
+ setAccessToken(null);
+ }
+ }
+ return response;
+ }
+
+ /**
+ * Destroy a specific user token on the server. The token will also be cleared
+ * from the UGClient instance, if it matches the token provided.
+ * Executes asynchronously in background and the callbacks are called in the UI thread.
+ *
+ * @param username The username to be logged out
+ * @param token The access token to be destroyed on the server
+ * @param callback A callback for the async response
+ */
+ public void logOutAppUserForTokenAsync(final String username, final String token, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return logOutAppUserForToken(username, token);
+ }
+ }).execute();
+ }
+
+ /**
+ * Log out a user and destroy all associated tokens on the server.
+ * The token stored in UGClient will also be destroyed.
+ *
+ * @param username The username to be logged out
+ * @return non-null ApiResponse if request succeeds
+ */
+ public ApiResponse logOutAppUserForAllTokens(String username) {
+ ApiResponse response = apiRequest(HTTP_METHOD_PUT, null, null,
+ organizationId, applicationId, "users",username,"revoketokens");
+ if (response == null) {
+ return response;
+ } else {
+ logInfo("logoutAppUserForAllTokens(): Response: " + response);
+ setAccessToken(null);
+ }
+ return response;
+ }
+
+ /**
+ * Log out a user and destroy all associated tokens on the server.
+ * The token stored in UGClient will also be destroyed.
+ * Executes asynchronously in background and the callbacks are called in the UI thread.
+ *
+ * @param username The username to be logged out
+ * @param callback A callback for the response
+ */
+ public void logOutAppUserForAllTokensAsync(final String username, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return logOutAppUserForAllTokens(username);
+ }
+ }).execute();
+ }
+
+ /**
+ * Log the app in with it's application (not organization) client id and
+ * client secret key. Not recommended for production apps.
+ *
+ * @param clientId the Usergrid application's client ID
+ * @param clientSecret the Usergrid application's client secret
+ */
+ public ApiResponse authorizeAppClient(String clientId, String clientSecret) {
+ validateNonEmptyParam(clientId, "client identifier");
+ validateNonEmptyParam(clientSecret, "client secret");
+ assertValidApplicationId();
+ loggedInUser = null;
+ accessToken = null;
+ currentOrganization = null;
+ Map<String, Object> formData = new HashMap<String, Object>();
+ formData.put("grant_type", "client_credentials");
+ formData.put("client_id", clientId);
+ formData.put("client_secret", clientSecret);
+ ApiResponse response = apiRequest(HTTP_METHOD_POST, formData, null,
+ organizationId, applicationId, "token");
+ if (response == null) {
+ return response;
+ }
+ if (!isEmpty(response.getAccessToken())) {
+ loggedInUser = null;
+ accessToken = response.getAccessToken();
+ currentOrganization = null;
+ logInfo("authorizeAppClient(): Access token: "
+ + accessToken);
+ } else {
+ logInfo("authorizeAppClient(): Response: " + response);
+ }
+ return response;
+ }
+
+
+ /****************** GENERIC ENTITY MANAGEMENT ***********************/
+ /****************** GENERIC ENTITY MANAGEMENT ***********************/
+
+ /**
+ * Create a new entity on the server.
+ *
+ * @param entity
+ * @return an ApiResponse with the new entity in it.
+ */
+ public ApiResponse createEntity(Entity entity) {
+ assertValidApplicationId();
+ if (isEmpty(entity.getType())) {
+ throw new IllegalArgumentException("Missing entity type");
+ }
+ ApiResponse response = apiRequest(HTTP_METHOD_POST, null, entity,
+ organizationId, applicationId, entity.getType());
+ return response;
+ }
+
+ /**
+ * Create a new entity on the server from a set of properties. Properties
+ * must include a "type" property.
+ *
+ * @param properties
+ * @return an ApiResponse with the new entity in it.
+ */
+ public ApiResponse createEntity(Map<String, Object> properties) {
+ assertValidApplicationId();
+ if (isEmpty(properties.get("type"))) {
+ throw new IllegalArgumentException("Missing entity type");
+ }
+ ApiResponse response = apiRequest(HTTP_METHOD_POST, null, properties,
+ organizationId, applicationId, properties.get("type").toString());
+ return response;
+ }
+
+ /**
+ * Create a new entity on the server. Executes asynchronously in background
+ * and the callbacks are called in the UI thread.
+ *
+ * @param entity An instance with data to use to create the entity
+ * @param callback A callback for the async response
+ */
+ public void createEntityAsync(final Entity entity,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return createEntity(entity);
+ }
+ }).execute();
+ }
+
+
+ /**
+ * Create a new entity on the server from a set of properties. Properties
+ * must include a "type" property. Executes asynchronously in background and
+ * the callbacks are called in the UI thread.
+ *
+ * @param properties The values to use, with keys as property names and values
+ * as property values
+ * @param callback A callback for the async response
+ */
+ public void createEntityAsync(final Map<String, Object> properties,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return createEntity(properties);
+ }
+ }).execute();
+ }
+
+ /**
+ * Create a set of entities on the server from an ArrayList. Each item in the array
+ * contains a set of properties that define a entity.
+ *
+ * @param type The type of entities to create.
+ * @param entities A list of maps where keys are entity property names and values
+ * are property values.
+ * @return An instance with response data from the server.
+ */
+ public ApiResponse createEntities(String type, ArrayList<Map<String, Object>> entities) {
+ assertValidApplicationId();
+ if (isEmpty(type)) {
+ throw new IllegalArgumentException("Missing entity type");
+ }
+ ApiResponse response = apiRequest(HTTP_METHOD_POST, null, entities,
+ organizationId, applicationId, type);
+ return response;
+ }
+
+ /**
+ * Create a set of entities on the server from an ArrayList. Each item in the array
+ * contains a set of properties that define a entity. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param type The type of entities to create.
+ * @param entities A list of maps where keys are entity property names and values
+ * are property values.
+ * @param callback A callback for the async response
+ */
+ public void createEntitiesAsync(final String type, final ArrayList<Map<String, Object>> entities,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return createEntities(type, entities);
+ }
+ }).execute();
+ }
+
+ /**
+ * Creates an object instance that corresponds to the provided entity type.
+ * Supported object types are Activity, Device, Group, Message, and User.
+ * All other types will return a generic Entity instance with no type assigned.
+ *
+ * @param type the entity type of which to create an object instance
+ * @return an object instance that corresponds to the type provided
+ */
+ public Entity createTypedEntity(String type) {
+ Entity entity = null;
+
+ if( Activity.isSameType(type) ) {
+ entity = new Activity(this);
+ } else if( Device.isSameType(type) ) {
+ entity = new Device(this);
+ } else if( Group.isSameType(type) ) {
+ entity = new Group(this);
+ } else if( Message.isSameType(type) ) {
+ entity = new Message(this);
+ } else if( User.isSameType(type) ) {
+ entity = new User(this);
+ } else {
+ entity = new Entity(this);
+ }
+
+ return entity;
+ }
+
+ /**
+ * Requests all entities of specified type that match the provided query string.
+ *
+ * @param type the entity type to be retrieved
+ * @param queryString a query string to send with the request
+ * @return a non-null ApiResponse object if successful
+ */
+ public ApiResponse getEntities(String type,String queryString)
+ {
+ Map<String, Object> params = null;
+
+ if (queryString.length() > 0) {
+ params = new HashMap<String, Object>();
+ params.put("ql", queryString);
+ }
+
+ return apiRequest(HTTP_METHOD_GET, // method
+ params, // params
+ null, // data
+ organizationId,
+ applicationId,
+ type);
+ }
+
+ /**
+ * Asynchronously requests all entities of specified type that match the provided query string.
+ *
+ * @param type the entity type to be retrieved
+ * @param queryString a query string to send with the request
+ * @param callback an ApiResponseCallback to handle the async response
+ */
+ public void getEntitiesAsync(final String type,
+ final String queryString, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return getEntities(type, queryString);
+ }
+ }).execute();
+ }
+
+ /**
+ * Update an existing entity on the server.
+ *
+ * @param entityID the entity to update
+ * @param updatedProperties the new properties
+ * @return an ApiResponse with the updated entity in it.
+ */
+ public ApiResponse updateEntity(String entityID, Map<String, Object> updatedProperties) {
+ assertValidApplicationId();
+ if (isEmpty(updatedProperties.get("type"))) {
+ throw new IllegalArgumentException("Missing entity type");
+ }
+ ApiResponse response = apiRequest(HTTP_METHOD_PUT, null, updatedProperties,
+ organizationId, applicationId, updatedProperties.get("type").toString(), entityID);
+ return response;
+ }
+
+
+ /**
+ * Update an existing entity on the server. Properties
+ * must include a "type" property. Executes asynchronously in background and
+ * the callbacks are called in the UI thread.
+ *
+ * @param entityID the entity to update
+ * @param updatedProperties the new properties
+ * @param callback A callback for the async response
+ */
+ public void updateEntityAsync(final String entityID, final Map<String, Object> updatedProperties,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return updateEntity(entityID, updatedProperties);
+ }
+ }).execute();
+ }
+
+ /**
+ * Updates the password associated with a user entity
+ *
+ * @param usernameOrEmail the username or email address associated with the user entity
+ * @param oldPassword the user's old password
+ * @param newPassword the user's new password
+ * @return an ApiResponse with the updated entity in it.
+ */
+ public ApiResponse updateUserPassword(String usernameOrEmail, String oldPassword, String newPassword) {
+ Map<String,Object> updatedProperties = new HashMap<String,Object>();
+ updatedProperties.put("oldpassword", oldPassword);
+ updatedProperties.put("newpassword", newPassword);
+ return apiRequest(HTTP_METHOD_POST, null, updatedProperties,
+ organizationId, applicationId, "users", usernameOrEmail);
+ }
+
+
+ /**
+ * Remove an existing entity on the server.
+ *
+ * @param entityType the collection of the entity
+ * @param entityID the specific entity to delete
+ * @return an ApiResponse indicating whether the removal was successful
+ */
+ public ApiResponse removeEntity(String entityType, String entityID) {
+ assertValidApplicationId();
+ if (isEmpty(entityType)) {
+ throw new IllegalArgumentException("Missing entity type");
+ }
+ ApiResponse response = apiRequest(HTTP_METHOD_DELETE, null, null,
+ organizationId, applicationId, entityType, entityID);
+ return response;
+ }
+
+ /**
+ * Remove an existing entity on the server.
+ * Executes asynchronously in background and
+ * the callbacks are called in the UI thread.
+ *
+ * @param entityType the collection of the entity
+ * @param entityID the specific entity to delete
+ * @param callback A callback with the async response
+ */
+ public void removeEntityAsync(final String entityType, final String entityID,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return removeEntity(entityType, entityID);
+ }
+ }).execute();
+ }
+
+ /**
+ * Perform a query request and return a query object. The Query object
+ * provides a simple way of dealing with result sets that need to be
+ * iterated or paged through.
+ *
+ * See {@link #doHttpRequest(String,Map,Object,String...)} for
+ * more on the parameters.
+ *
+ * @param httpMethod The HTTP method to use in the query
+ * @param params Query parameters.
+ * @param data The request body.
+ * @param segments Additional URL path segments to append to the request URL
+ * @return An instance representing query results
+ */
+ public Query queryEntitiesRequest(String httpMethod,
+ Map<String, Object> params, Object data, String... segments) {
+ ApiResponse response = apiRequest(httpMethod, params, data, segments);
+ return new EntityQuery(response, httpMethod, params, data, segments);
+ }
+
+ /**
+ * Perform a query request and return a query object. The Query object
+ * provides a simple way of dealing with result sets that need to be
+ * iterated or paged through. Executes asynchronously in background and the
+ * callbacks are called in the UI thread.
+ *
+ * See {@link #doHttpRequest(String,Map,Object,String...)} for
+ * more on the parameters.
+ *
+ * @param callback A callback for the async response
+ * @param httpMethod The HTTP method to use in the query
+ * @param params Query parameters.
+ * @param data The request body.
+ * @param segments Additional URL path segments to append to the request URL
+ */
+ public void queryEntitiesRequestAsync(final QueryResultsCallback callback,
+ final String httpMethod, final Map<String, Object> params,
+ final Object data, final String... segments) {
+ (new ClientAsyncTask<Query>(callback) {
+ @Override
+ public Query doTask() {
+ return queryEntitiesRequest(httpMethod, params, data, segments);
+ }
+ }).execute();
+ }
+
+ /**
+ * Query object for handling the response from certain query requests
+ * @y.exclude
+ */
+ private class EntityQuery implements Query {
+ final String httpMethod;
+ final Map<String, Object> params;
+ final Object data;
+ final String[] segments;
+ final ApiResponse response;
+
+ private EntityQuery(ApiResponse response, String httpMethod,
+ Map<String, Object> params, Object data, String[] segments) {
+ this.response = response;
+ this.httpMethod = httpMethod;
+ this.params = params;
+ this.data = data;
+ this.segments = segments;
+ }
+
+ private EntityQuery(ApiResponse response, EntityQuery q) {
+ this.response = response;
+ httpMethod = q.httpMethod;
+ params = q.params;
+ data = q.data;
+ segments = q.segments;
+ }
+
+ /**
+ * Gets the API response from the last request
+ *
+ * @return an ApiResponse object
+ */
+ public ApiResponse getResponse() {
+ return response;
+ }
+
+ /**
+ * Checks if there are more results available based on whether a
+ * 'cursor' property was present in the last result set.
+ *
+ * @return true if the server indicates more results are available
+ */
+ public boolean more() {
+ if ((response != null) && (response.getCursor() != null)
+ && (response.getCursor().length() > 0)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Performs a request for the next set of results based on the cursor
+ * from the last result set.
+ *
+ * @return query that contains results and where to get more.
+ */
+ public Query next() {
+ if (more()) {
+ Map<String, Object> nextParams = null;
+ if (params != null) {
+ nextParams = new HashMap<String, Object>(params);
+ } else {
+ nextParams = new HashMap<String, Object>();
+ }
+ nextParams.put("cursor", response.getCursor());
+ ApiResponse nextResponse = apiRequest(httpMethod, nextParams, data,
+ segments);
+ return new EntityQuery(nextResponse, this);
+ }
+ return null;
+ }
+
+ }
+
+
+ /****************** USER ENTITY MANAGEMENT ***********************/
+ /****************** USER ENTITY MANAGEMENT ***********************/
+
+ /**
+ * Creates a user entity.
+ *
+ * @param username required. The username to be associated with the user entity.
+ * @param name the user's full name. Can be null.
+ * @param email the user's email address.
+ * @param password the user's password
+ * @return an ApiResponse object
+ */
+ public ApiResponse createUser(String username, String name, String email,
+ String password) {
+ Map<String, Object> properties = new HashMap<String, Object>();
+ properties.put("type", "user");
+ if (username != null) {
+ properties.put("username", username);
+ }
+ if (name != null) {
+ properties.put("name", name);
+ }
+ if (email != null) {
+ properties.put("email", email);
+ }
+ if (password != null) {
+ properties.put("password", password);
+ }
+ return createEntity(properties);
+ }
+
+ /**
+ * Creates a user. Executes asynchronously in background and the callbacks
+ * are called in the UI thread.
+ *
+ * @param username required. The username to be associated with the user entity.
+ * @param name the user's full name. Can be null.
+ * @param email the user's email address.
+ * @param password the user's password.
+ * @param callback an ApiResponse callback for handling the async response.
+ */
+ public void createUserAsync(final String username, final String name,
+ final String email, final String password,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return createUser(username, name, email, password);
+ }
+ }).execute();
+ }
+
+ /**
+ * Retrieves the /users collection.
+ *
+ * @return a Query object
+ */
+ public Query queryUsers() {
+ Query q = queryEntitiesRequest(HTTP_METHOD_GET, null, null,
+ organizationId, applicationId, "users");
+ return q;
+ }
+
+ /**
+ * Retrieves the /users collection. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param callback a QueryResultsCallback object to handle the async response
+ */
+ public void queryUsersAsync(QueryResultsCallback callback) {
+ queryEntitiesRequestAsync(callback, HTTP_METHOD_GET, null, null,
+ organizationId, applicationId, "users");
+ }
+
+
+ /**
+ * Performs a query of the users collection using the provided query command.
+ * For example: "name contains 'ed'".
+ *
+ * @param ql the query to execute
+ * @return a Query object
+ */
+ public Query queryUsers(String ql) {
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put("ql", ql);
+ Query q = queryEntitiesRequest(HTTP_METHOD_GET, params, null,organizationId,
+ applicationId, "users");
+ return q;
+ }
+
+ /**
+ * Perform a query of the users collection using the provided query command.
+ * For example: "name contains 'ed'". Executes asynchronously in background
+ * and the callbacks are called in the UI thread.
+ *
+ * @param ql the query to execute
+ * @param callback a QueryResultsCallback object to handle the async response
+ */
+ public void queryUsersAsync(String ql, QueryResultsCallback callback) {
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put("ql", ql);
+ queryEntitiesRequestAsync(callback, HTTP_METHOD_GET, params, null,
+ organizationId, applicationId, "users");
+ }
+
+ /**
+ * Perform a query of the users collection within the specified distance of
+ * the specified location and optionally using the provided additional query.
+ * For example: "name contains 'ed'".
+ *
+ * @param distance distance from the location in meters
+ * @param latitude the latitude of the location to measure from
+ * @param longitude the longitude of the location to measure from
+ * @param ql an optional additional query to send with the request
+ * @return a Query object
+ */
+ public Query queryUsersWithinLocation(float distance, float latitude,
+ float longitude, String ql) {
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put("ql",
+ this.makeLocationQL(distance, latitude, longitude, ql));
+ Query q = queryEntitiesRequest(HTTP_METHOD_GET, params, null, organizationId,
+ applicationId, "users");
+ return q;
+ }
+
+
+ /****************** GROUP ENTITY MANAGEMENT ***********************/
+ /****************** GROUP ENTITY MANAGEMENT ***********************/
+
+ /**
+ * Creates a group with the specified group path. Group paths can be slash
+ * ("/") delimited like file paths for hierarchical group relationships.
+ *
+ * @param groupPath the path to use for the new group.
+ * @return an ApiResponse object
+ */
+ public ApiResponse createGroup(String groupPath) {
+ return createGroup(groupPath, null);
+ }
+
+ /**
+ * Creates a group with the specified group path and group title. Group
+ * paths can be slash ("/") delimited like file paths for hierarchical group
+ * relationships.
+ *
+ * @param groupPath the path to use for the new group
+ * @param groupTitle the title to use for the new group
+ * @return an ApiResponse object
+ */
+ public ApiResponse createGroup(String groupPath, String groupTitle) {
+ return createGroup(groupPath, groupTitle, null);
+ }
+
+ /**
+ * Create a group with a path, title and name. Group
+ * paths can be slash ("/") delimited like file paths for hierarchical group
+ * relationships.
+ *
+ * @param groupPath the path to use for the new group
+ * @param groupTitle the title to use for the new group
+ * @param groupName the name to use for the new group
+ * @return an ApiResponse object
+ */
+ public ApiResponse createGroup(String groupPath, String groupTitle, String groupName){
+ Map<String, Object> data = new HashMap<String, Object>();
+ data.put("type", "group");
+ data.put("path", groupPath);
+
+ if (groupTitle != null) {
+ data.put("title", groupTitle);
+ }
+
+ if(groupName != null){
+ data.put("name", groupName);
+ }
+
+ return apiRequest(HTTP_METHOD_POST, null, data, organizationId, applicationId, "groups");
+ }
+
+ /**
+ * Creates a group with the specified group path. Group paths can be slash
+ * ("/") delimited like file paths for hierarchical group relationships.
+ * Executes asynchronously in background and the callbacks are called in the
+ * UI thread.
+ *
+ * @param groupPath the path to use for the new group.
+ * @param callback an ApiResponseCallback object to handle the async response
+ */
+ public void createGroupAsync(String groupPath,
+ final ApiResponseCallback callback) {
+ createGroupAsync(groupPath, null, null);
+ }
+
+ /**
+ * Creates a group with the specified group path and group title. Group
+ * paths can be slash ("/") deliminted like file paths for hierarchical
+ * group relationships. Executes asynchronously in background and the
+ * callbacks are called in the UI thread.
+ *
+ * @param groupPath the path to use for the new group.
+ * @param groupTitle the title to use for the new group.
+ * @param callback an ApiResponseCallback object to handle the async response
+ */
+ public void createGroupAsync(final String groupPath,
+ final String groupTitle, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return createGroup(groupPath, groupTitle);
+ }
+ }).execute();
+ }
+
+ /**
+ * Gets the groups associated with a user entity
+ *
+ * @param userId the UUID of the user entity
+ * @return a map with the group path as the key and a Group object as the value
+ */
+ public Map<String, Group> getGroupsForUser(String userId) {
+ ApiResponse response = apiRequest(HTTP_METHOD_GET, null, null,
+ organizationId, applicationId, "users", userId, "groups");
+ Map<String, Group> groupMap = new HashMap<String, Group>();
+ if (response != null) {
+ List<Group> groups = response.getEntities(Group.class);
+ for (Group group : groups) {
+ groupMap.put(group.getPath(), group);
+ }
+ }
+ return groupMap;
+ }
+
+ /**
+ * Gets the groups associated with a user entity. Executes asynchronously in background and
+ * the callbacks are called in the UI thread.
+ *
+ * @param userId the UUID of the user entity
+ * @param callback a GroupsRetrievedCallback object to handle the async response
+ */
+ public void getGroupsForUserAsync(final String userId,
+ final GroupsRetrievedCallback callback) {
+ (new ClientAsyncTask<Map<String, Group>>(callback) {
+ @Override
+ public Map<String, Group> doTask() {
+ return getGroupsForUser(userId);
+ }
+ }).execute();
+ }
+
+ /**
+ * Gets the user entities associated with the specified group.
+ *
+ * @param groupId UUID of the group entity
+ * @return a Query object with the results of the query
+ */
+ public Query queryUsersForGroup(String groupId) {
+ Query q = queryEntitiesRequest(HTTP_METHOD_GET, null, null, organizationId,
+ applicationId, "groups", groupId, "users");
+ return q;
+ }
+
+ /**
+ * Gets the user entities associated with the specified group. Executes
+ * asynchronously in background and the callbacks are called in the UI thread.
+ *
+ * @param groupId UUID of the group entity
+ * @param callback a QueryResultsCallback object to handle the async response
+ */
+ public void queryUsersForGroupAsync(String groupId,
+ QueryResultsCallback callback) {
+ queryEntitiesRequestAsync(callback, HTTP_METHOD_GET, null, null,
+ getApplicationId(), "groups", groupId, "users");
+ }
+
+ /**
+ * Connects a user entity to the specified group entity.
+ *
+ * @param userId UUID of the user entity
+ * @param groupId UUID of the group entity
+ * @return an ApiResponse object
+ */
+ public ApiResponse addUserToGroup(String userId, String groupId) {
+ return apiRequest(HTTP_METHOD_POST, null, null, organizationId, applicationId, "groups",
+ groupId, "users", userId);
+ }
+
+ /**
+ * Connects a user entity to the specified group entity. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param userId UUID of the user entity
+ * @param groupId UUID of the group entity
+ * @param callback an ApiResponseCallback object to handle the async response
+ */
+ public void addUserToGroupAsync(final String userId, final String groupId,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return addUserToGroup(userId, groupId);
+ }
+ }).execute();
+ }
+
+ /**
+ * Disconnects a user entity from the specified group entity.
+ *
+ * @param userId UUID of the user entity
+ * @param groupId UUID of the group entity
+ * @return an ApiResponse object
+ */
+ public ApiResponse removeUserFromGroup(String userId, String groupId) {
+ return apiRequest(HTTP_METHOD_DELETE, null, null, organizationId, applicationId, "groups",
+ groupId, "users", userId);
+ }
+
+ /**
+ * Disconnects a user entity from the specified group entity. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param userId UUID of the user entity
+ * @param groupId UUID of the group entity
+ * @param callback an ApiResponseCallback object to handle the async response
+ */
+ public void removeUserFromGroupAsync(final String userId, final String groupId,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return removeUserFromGroup(userId, groupId);
+ }
+ }).execute();
+ }
+
+ /****************** ACTIVITY ENTITY MANAGEMENT ***********************/
+ /****************** ACTIVITY ENTITY MANAGEMENT ***********************/
+
+ /**
+ * Get a user's activity feed. Returned as a query to ease paging.
+ *
+ * @param userId UUID of user entity
+ * @return a Query object
+ */
+ public Query queryActivityFeedForUser(String userId) {
+ Query q = queryEntitiesRequest(HTTP_METHOD_GET, null, null,
+ organizationId, applicationId, "users", userId, "feed");
+ return q;
+ }
+
+ /**
+ * Get a user's activity feed. Returned as a query to ease paging. Executes
+ * asynchronously in background and the callbacks are called in the UI
+ * thread.
+ *
+ *
+ * @param userId UUID of user entity
+ * @param callback a QueryResultsCallback object to handle the async response
+ */
+ public void queryActivityFeedForUserAsync(final String userId, final QueryResultsCallback callback) {
+ (new ClientAsyncTask<Query>(callback) {
+ @Override
+ public Query doTask() {
+ return queryActivityFeedForUser(userId);
+ }
+ }).execute();
+ }
+
+
+ /**
+ * Posts an activity to a user entity's activity stream. Activity must already be created.
+ *
+ * @param userId
+ * @param activity
+ * @return An instance with the server response
+ */
+ public ApiResponse postUserActivity(String userId, Activity activity) {
+ return apiRequest(HTTP_METHOD_POST, null, activity, organizationId, applicationId, "users",
+ userId, "activities");
+ }
+
+ /**
+ * Creates and posts an activity to a user entity's activity stream.
+ *
+ * @param verb
+ * @param title
+ * @param content
+ * @param category
+ * @param user
+ * @param object
+ * @param objectType
+ * @param objectName
+ * @param objectContent
+ * @return
+ */
+ public ApiResponse postUserActivity(String verb, String title,
+ String content, String category, User user, Entity object,
+ String objectType, String objectName, String objectContent) {
+ Activity activity = Activity.newActivity(this, verb, title, content,
+ category, user, object, objectType, objectName, objectContent);
+ return postUserActivity(user.getUuid().toString(), activity);
+ }
+
+ /**
+ * Creates and posts an activity to a user. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param verb
+ * @param title
+ * @param content
+ * @param category
+ * @param user
+ * @param object
+ * @param objectType
+ * @param objectName
+ * @param objectContent
+ * @param callback
+ */
+ public void postUserActivityAsync(final String verb, final String title,
+ final String content, final String category, final User user,
+ final Entity object, final String objectType,
+ final String objectName, final String objectContent,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return postUserActivity(verb, title, content, category, user,
+ object, objectType, objectName, objectContent);
+ }
+ }).execute();
+ }
+
+ /**
+ * Posts an activity to a group. Activity must already be created.
+ *
+ * @param groupId
+ * @param activity
+ * @return
+ */
+ public ApiResponse postGroupActivity(String groupId, Activity activity) {
+ return apiRequest(HTTP_METHOD_POST, null, activity, organizationId, applicationId, "groups",
+ groupId, "activities");
+ }
+
+ /**
+ * Creates and posts an activity to a group.
+ *
+ * @param groupId
+ * @param verb
+ * @param title
+ * @param content
+ * @param category
+ * @param user
+ * @param object
+ * @param objectType
+ * @param objectName
+ * @param objectContent
+ * @return
+ */
+ public ApiResponse postGroupActivity(String groupId, String verb, String title,
+ String content, String category, User user, Entity object,
+ String objectType, String objectName, String objectContent) {
+ Activity activity = Activity.newActivity(this, verb, title, content,
+ category, user, object, objectType, objectName, objectContent);
+ return postGroupActivity(groupId, activity);
+ }
+
+ /**
+ * Creates and posts an activity to a group. Executes asynchronously in
+ * background and the callbacks are called in the UI thread.
+ *
+ * @param groupId
+ * @param verb
+ * @param title
+ * @param content
+ * @param category
+ * @param user
+ * @param object
+ * @param objectType
+ * @param objectName
+ * @param objectContent
+ * @param callback
+ */
+ public void postGroupActivityAsync(final String groupId, final String verb, final String title,
+ final String content, final String category, final User user,
+ final Entity object, final String objectType,
+ final String objectName, final String objectContent,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return postGroupActivity(groupId, verb, title, content, category, user,
+ object, objectType, objectName, objectContent);
+ }
+ }).execute();
+ }
+
+ /**
+ * Post an activity to the stream.
+ *
+ * @param activity
+ * @return
+ */
+ public ApiResponse postActivity(Activity activity) {
+ return createEntity(activity);
+ }
+
+ /**
+ * Creates and posts an activity to a group.
+ *
+ * @param verb
+ * @param title
+ * @param content
+ * @param category
+ * @param user
+ * @param object
+ * @param objectType
+ * @param objectName
+ * @param objectContent
+ * @return
+ */
+ public ApiResponse postActivity(String verb, String title,
+ String content, String category, User user, Entity object,
+ String objectType, String objectName, String objectContent) {
+ Activity activity = Activity.newActivity(this, verb, title, content,
+ category, user, object, objectType, objectName, objectContent);
+ return createEntity(activity);
+ }
+
+ /**
+ * Get a group's activity feed. Returned as a query to ease paging.
+ *
+ * @return
+ */
+ public Query queryActivity() {
+ Query q = queryEntitiesRequest(HTTP_METHOD_GET, null, null,
+ organizationId, applicationId, "activities");
+ return q;
+ }
+
+
+
+ /**
+ * Get a group's activity feed. Returned as a query to ease paging.
+ *
+ * @param groupId
+ * @return
+ */
+ public Query queryActivityFeedForGroup(String groupId) {
+ Query q = queryEntitiesRequest(HTTP_METHOD_GET, null, null,
+ organizationId, applicationId, "groups", groupId, "feed");
+ return q;
+ }
+
+ /**
+ * Get a group's activity feed. Returned as a query to ease paging. Executes
+ * asynchronously in background and the callbacks are called in the UI
+ * thread.
+ *
+ *
+ * @param groupId
+ * @param callback
+ */
+ public void queryActivityFeedForGroupAsync(final String groupId,
+ final QueryResultsCallback callback) {
+ (new ClientAsyncTask<Query>(callback) {
+ @Override
+ public Query doTask() {
+ return queryActivityFeedForGroup(groupId);
+ }
+ }).execute();
+ }
+
+
+ /****************** ENTITY CONNECTIONS ***********************/
+ /****************** ENTITY CONNECTIONS ***********************/
+
+ /**
+ * Connect two entities together.
+ *
+ * @param connectingEntityType The type of the first entity.
+ * @param connectingEntityId The ID of the first entity.
+ * @param connectionType The type of connection between the entities.
+ * @param connectedEntityId The ID of the second entity.
+ * @return An instance with the server's response.
+ */
+ public ApiResponse connectEntities(String connectingEntityType,
+ String connectingEntityId, String connectionType,
+ String connectedEntityId) {
+ return apiRequest(HTTP_METHOD_POST, null, null, organizationId, applicationId,
+ connectingEntityType, connectingEntityId, connectionType,
+ connectedEntityId);
+ }
+
+ /**
+ * Connect two entities together
+ *
+ * @param connectorType The type of the first entity in the connection.
+ * @param connectorID The first entity's ID.
+ * @param connectionType The type of connection to make.
+ * @param connecteeType The type of the second entity.
+ * @param connecteeID The second entity's ID
+ * @return An instance with the server's response.
+ */
+ public ApiResponse connectEntities(String connectorType,
+ String connectorID,
+ String connectionType,
+ String connecteeType,
+ String connecteeID) {
+ return apiRequest(HTTP_METHOD_POST, null, null, organizationId, applicationId,
+ connectorType, connectorID, connectionType, connecteeType, connecteeID);
+ }
+
+
+ /**
+ * Connect two entities together. Executes asynchronously in background and
+ * the callbacks are called in the UI thread.
+ *
+ * @param connectingEntityType The type of the first entity.
+ * @param connectingEntityId The UUID or 'name' property of the first entity.
+ * @param connectionType The type of connection between the entities.
+ * @param connectedEntityId The UUID of the second entity.
+ * @param callback A callback with the async response.
+ */
+ public void connectEntitiesAsync(final String connectingEntityType,
+ final String connectingEntityId, final String connectionType,
+ final String connectedEntityId, final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return connectEntities(connectingEntityType,
+ connectingEntityId, connectionType, connectedEntityId);
+ }
+ }).execute();
+ }
+
+ /**
+ * Connect two entities together. Allows the 'name' of the connected entity
+ * to be specified but requires the type also be specified. Executes asynchronously
+ * in background and the callbacks are called in the UI thread.
+ *
+ * @param connectingEntityType The type of the first entity.
+ * @param connectingEntityId The UUID or 'name' property of the first entity.
+ * @param connectionType The type of connection between the entities.
+ * @param connectedEntityType The type of connection between the entities.
+ * @param connectedEntityId The UUID or 'name' property of the second entity.
+ * @param callback A callback with the async response.
+ */
+ public void connectEntitiesAsync(final String connectingEntityType,
+ final String connectingEntityId, final String connectionType,
+ final String connectedEntityType, final String connectedEntityId,
+ final ApiResponseCallback callback) {
+ (new ClientAsyncTask<ApiResponse>(callback) {
+ @Override
+ public ApiResponse doTask() {
+ return connectEntities(connectingEntityType,
+ connectingEntityId, connectionType, connectedEntityType, connectedEntityId);
+ }
+ }).execute();
+ }
+
+ /**
+ * Disconnect two entities.
+ *
+ * @param connectingEntityType The collection name or UUID of the first entity.
+ * @param connectingEntityId The name or UUID of the first entity.
+ * @param connectionType The type of connection between the entities.
+ * @param connectedEntityId The name or UUID of the second entity.
+ * @return An instance with the server's response.
+ */
+ public ApiResponse disconnectEntities(String connectingEntityType,
+ String connectingEntityId, String connectionType,
+ String connectedEntity
<TRUNCATED>