You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2014/08/26 14:28:19 UTC

[05/26] Add the old 0.0.6 Java SDK code because the Android SDK needs it.

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c08a2791/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/Client.java
----------------------------------------------------------------------
diff --git a/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/Client.java b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/Client.java
new file mode 100644
index 0000000..2e648fe
--- /dev/null
+++ b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/Client.java
@@ -0,0 +1,1292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.usergrid.java.client;
+
+import static org.springframework.util.StringUtils.arrayToDelimitedString;
+import static org.springframework.util.StringUtils.tokenizeToStringArray;
+import static org.usergrid.java.client.utils.JsonUtils.parse;
+import static org.usergrid.java.client.utils.ObjectUtils.isEmpty;
+import static org.usergrid.java.client.utils.UrlUtils.addQueryParams;
+import static org.usergrid.java.client.utils.UrlUtils.encodeParams;
+import static org.usergrid.java.client.utils.UrlUtils.path;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestTemplate;
+import org.usergrid.java.client.entities.Activity;
+import org.usergrid.java.client.entities.Device;
+import org.usergrid.java.client.entities.Entity;
+import org.usergrid.java.client.entities.Group;
+import org.usergrid.java.client.entities.User;
+import org.usergrid.java.client.response.ApiResponse;
+
+/**
+ * The Client class for accessing the Usergrid API. Start by instantiating this
+ * class though the appropriate constructor.
+ * 
+ */
+public class Client {
+
+    private static final Logger log = LoggerFactory.getLogger(Client.class);
+
+    public static boolean FORCE_PUBLIC_API = false;
+
+    // Public API
+    public static String PUBLIC_API_URL = "http://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;
+
+    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;
+
+    static RestTemplate restTemplate = new RestTemplate(true);
+
+    /**
+     * Default constructor for instantiating a client.
+     */
+    public Client() {
+        init();
+    }
+
+    /**
+     * Instantiate client for a specific app
+     * 
+     * @param applicationId
+     *            the application id or name
+     */
+    public Client(String organizationId, String applicationId) {
+        init();
+        this.organizationId = organizationId;
+        this.applicationId = applicationId;
+    }
+
+    public void init() {
+
+    }
+
+    /**
+     * @return the Usergrid API url (default: http://api.usergrid.com)
+     */
+    public String getApiUrl() {
+        return apiUrl;
+    }
+
+    /**
+     * @param apiUrl
+     *            the Usergrid API url (default: http://api.usergrid.com)
+     */
+    public void setApiUrl(String apiUrl) {
+        this.apiUrl = apiUrl;
+    }
+
+    /**
+     * @param apiUrl
+     *            the Usergrid API url (default: http://api.usergrid.com)
+     * @return Client object for method call chaining
+     */
+    public Client withApiUrl(String apiUrl) {
+        this.apiUrl = apiUrl;
+        return this;
+    }
+    
+    
+    /**
+     * the organizationId to set
+     * @param organizationId
+     * @return
+     */
+    public Client withOrganizationId(String organizationId){
+        this.organizationId = organizationId;
+        return this;
+    }
+    
+    
+
+    /**
+     * @return the organizationId
+     */
+    public String getOrganizationId() {
+        return organizationId;
+    }
+
+    /**
+     * @param organizationId the organizationId to set
+     */
+    public void setOrganizationId(String organizationId) {
+        this.organizationId = organizationId;
+    }
+
+    /**
+     * @return the application id or name
+     */
+    public String getApplicationId() {
+        return applicationId;
+    }
+
+    /**
+     * @param applicationId
+     *            the application id or name
+     */
+    public void setApplicationId(String applicationId) {
+        this.applicationId = applicationId;
+    }
+   
+
+    /**
+     * @param applicationId
+     *            the application id or name
+     * @return Client object for method call chaining
+     */
+    public Client withApplicationId(String applicationId) {
+        this.applicationId = applicationId;
+        return this;
+    }
+
+    /**
+     * @return the client key id for making calls as the application-owner. Not
+     *         safe for most mobile use.
+     */
+    public String getClientId() {
+        return clientId;
+    }
+
+    /**
+     * @param clientId
+     *            the client key id for making calls as the application-owner.
+     *            Not safe for most mobile use.
+     */
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    /**
+     * @param clientId
+     *            the client key id for making calls as the application-owner.
+     *            Not safe for most mobile use.
+     * @return Client object for method call chaining
+     */
+    public Client withClientId(String clientId) {
+        this.clientId = clientId;
+        return this;
+    }
+
+    /**
+     * @return the client key id for making calls as the application-owner. Not
+     *         safe for most mobile use.
+     */
+    public String getClientSecret() {
+        return clientSecret;
+    }
+
+    /**
+     * @param clientSecret
+     *            the client key id for making calls as the application-owner.
+     *            Not safe for most mobile use.
+     */
+    public void setClientSecret(String clientSecret) {
+        this.clientSecret = clientSecret;
+    }
+
+    /**
+     * @param clientSecret
+     *            the client key id for making calls as the application-owner.
+     *            Not safe for most mobile use.
+     * @return Client object for method call chaining
+     */
+    public Client withClientSecret(String clientSecret) {
+        this.clientSecret = clientSecret;
+        return this;
+    }
+
+    /**
+     * @return the logged-in user after a successful authorizeAppUser request
+     */
+    public User getLoggedInUser() {
+        return loggedInUser;
+    }
+
+    /**
+     * @param loggedInUser
+     *            the logged-in user, usually not set by host application
+     */
+    public void setLoggedInUser(User loggedInUser) {
+        this.loggedInUser = loggedInUser;
+    }
+
+    /**
+     * @return the OAuth2 access token after a successful authorize request
+     */
+    public String getAccessToken() {
+        return accessToken;
+    }
+
+    /**
+     * @param accessToken
+     *            an OAuth2 access token. Usually not set by host application
+     */
+    public void setAccessToken(String accessToken) {
+        this.accessToken = accessToken;
+    }
+
+    /**
+     * @return the currentOrganization
+     */
+    public String getCurrentOrganization() {
+        return currentOrganization;
+    }
+
+    /**
+     * @param currentOrganization
+     */
+    public void setCurrentOrganization(String currentOrganization) {
+        this.currentOrganization = currentOrganization;
+    }
+
+    /**
+     * Low-level HTTP request method. Synchronous, blocks till response or
+     * timeout.
+     * 
+     * @param method
+     *            HttpMethod method
+     * @param cls
+     *            class for the return type
+     * @param params
+     *            parameters to encode as querystring or body parameters
+     * @param data
+     *            JSON data to put in body
+     * @param segments
+     *            REST url path segments (i.e. /segment1/segment2/segment3)
+     * @return results marshalled into class specified in cls parameter
+     */
+    public <T> T httpRequest(HttpMethod method, Class<T> cls,
+            Map<String, Object> params, Object data, String... segments) {
+        HttpHeaders requestHeaders = new HttpHeaders();
+        requestHeaders.setAccept(Collections
+                .singletonList(MediaType.APPLICATION_JSON));
+        if (accessToken != null) {
+            String auth = "Bearer " + accessToken;
+            requestHeaders.set("Authorization", auth);
+            log.info("Authorization: " + auth);
+        }
+        String url = path(apiUrl, segments);
+
+        MediaType contentType = MediaType.APPLICATION_JSON;
+        if (method.equals(HttpMethod.POST) && isEmpty(data) && !isEmpty(params)) {
+            data = encodeParams(params);
+            contentType = MediaType.APPLICATION_FORM_URLENCODED;
+        } else {
+            url = addQueryParams(url, params);
+        }
+        requestHeaders.setContentType(contentType);
+        HttpEntity<?> requestEntity = null;
+
+        if (method.equals(HttpMethod.POST) || method.equals(HttpMethod.PUT)) {
+            if (isEmpty(data)) {
+                data = JsonNodeFactory.instance.objectNode();
+            }
+            requestEntity = new HttpEntity<Object>(data, requestHeaders);
+        } else {
+            requestEntity = new HttpEntity<Object>(requestHeaders);
+        }
+        log.info("Client.httpRequest(): url: " + url);
+        ResponseEntity<T> responseEntity = restTemplate.exchange(url, method,
+                requestEntity, cls);
+        log.info("Client.httpRequest(): reponse body: "
+                + responseEntity.getBody().toString());
+        return responseEntity.getBody();
+    }
+
+    /**
+     * High-level Usergrid API request.
+     * 
+     * @param method
+     * @param params
+     * @param data
+     * @param segments
+     * @return
+     */
+    public ApiResponse apiRequest(HttpMethod method,
+            Map<String, Object> params, Object data, String... segments) {
+        ApiResponse response = null;
+        try {
+            response = httpRequest(method, ApiResponse.class, params, data,
+                    segments);
+            log.info("Client.apiRequest(): Response: " + response);
+        } catch (HttpClientErrorException e) {
+            log.error("Client.apiRequest(): HTTP error: "
+                    + e.getLocalizedMessage());
+            response = parse(e.getResponseBodyAsString(), ApiResponse.class);
+            if ((response != null) && !isEmpty(response.getError())) {
+                log.error("Client.apiRequest(): Response error: "
+                        + response.getError());
+                if (!isEmpty(response.getException())) {
+                    log.error("Client.apiRequest(): Response exception: "
+                            + response.getException());
+                }
+            }
+        }
+        return response;
+    }
+
+    protected void assertValidApplicationId() {
+        if (isEmpty(applicationId)) {
+            throw new IllegalArgumentException("No application id specified");
+        }
+    }
+
+    /**
+     * Log the user in and get a valid access token.
+     * 
+     * @param email
+     * @param password
+     * @return non-null ApiResponse if request succeeds, check getError() for
+     *         "invalid_grant" to see if access is denied.
+     */
+    public ApiResponse authorizeAppUser(String email, String password) {
+        validateNonEmptyParam(email, "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", email);
+        formData.put("password", password);
+        ApiResponse response = apiRequest(HttpMethod.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;
+            log.info("Client.authorizeAppUser(): Access token: " + accessToken);
+        } else {
+            log.info("Client.authorizeAppUser(): Response: " + response);
+        }
+        return response;
+    }
+
+    /**
+     * Change the password for the currently logged in user. You must supply the
+     * old password and the new password.
+     * 
+     * @param username
+     * @param oldPassword
+     * @param newPassword
+     * @return
+     */
+    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(HttpMethod.POST, null, data, organizationId,  applicationId, "users",
+                username, "password");
+
+    }
+
+    /**
+     * Log the user in with their numeric pin-code and get a valid access token.
+     * 
+     * @param email
+     * @param pin
+     * @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(HttpMethod.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;
+            log.info("Client.authorizeAppUser(): Access token: " + accessToken);
+        } else {
+            log.info("Client.authorizeAppUser(): Response: " + response);
+        }
+        return response;
+    }
+
+    /**
+     * Log the user in with their Facebook access token retrived via Facebook
+     * OAuth.
+     * 
+     * @param email
+     * @param pin
+     * @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(HttpMethod.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;
+            log.info("Client.authorizeAppUserViaFacebook(): Access token: "
+                    + accessToken);
+        } else {
+            log.info("Client.authorizeAppUserViaFacebook(): Response: "
+                    + response);
+        }
+        return response;
+    }
+
+    /**
+     * Log the app in with it's client id and client secret key. Not recommended
+     * for production apps.
+     * 
+     * @param email
+     * @param pin
+     * @return non-null ApiResponse if request succeeds, check getError() for
+     *         "invalid_grant" to see if access is denied.
+     */
+    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(HttpMethod.POST, formData, null,
+                organizationId, applicationId, "token");
+        if (response == null) {
+            return response;
+        }
+        if (!isEmpty(response.getAccessToken())) {
+            loggedInUser = null;
+            accessToken = response.getAccessToken();
+            currentOrganization = null;
+            log.info("Client.authorizeAppClient(): Access token: "
+                    + accessToken);
+        } else {
+            log.info("Client.authorizeAppClient(): Response: " + response);
+        }
+        return response;
+    }
+
+    private void validateNonEmptyParam(Object param, String paramName) {
+        if ( isEmpty(param) ) {
+            throw new IllegalArgumentException(paramName + " cannot be null or empty");
+        }
+    }
+
+    /**
+     * Registers a device using the device's unique device ID.
+     * 
+     * @param context
+     * @param properties
+     * @return a Device object if success
+     */
+    public Device registerDevice(UUID deviceId, Map<String, Object> properties) {
+        assertValidApplicationId();
+        if (properties == null) {
+            properties = new HashMap<String, Object>();
+        }
+        properties.put("refreshed", System.currentTimeMillis());
+        ApiResponse response = apiRequest(HttpMethod.PUT, null, properties,
+                organizationId, applicationId, "devices", deviceId.toString());
+        return response.getFirstEntity(Device.class);
+    }
+
+    /**
+     * Registers a device using the device's unique device ID.
+     *
+     * @param context
+     * @param properties
+     * @return a Device object if success
+     */
+    public Device registerDeviceForPush(UUID deviceId,
+                                        String notifier,
+                                        String token,
+                                        Map<String, Object> properties) {
+      if (properties == null) {
+          properties = new HashMap<String, Object>();
+      }
+      String notifierKey = notifier + ".notifier.id";
+      properties.put(notifierKey, token);
+      return registerDevice(deviceId, properties);
+    }
+
+    /**
+     * 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(HttpMethod.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(HttpMethod.POST, null, properties,
+                organizationId, applicationId, properties.get("type").toString());
+        return response;
+    }
+
+    /**
+     * Creates a user.
+     * 
+     * @param username
+     *            required
+     * @param name
+     * @param email
+     * @param password
+     * @return
+     */
+    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);
+    }
+
+    /**
+     * Get the groups for the user.
+     * 
+     * @param userId
+     * @return a map with the group path as the key and the Group entity as the
+     *         value
+     */
+    public Map<String, Group> getGroupsForUser(String userId) {
+        ApiResponse response = apiRequest(HttpMethod.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;
+    }
+
+    /**
+     * Get a user's activity feed. Returned as a query to ease paging.
+     * 
+     * @param userId
+     * @return
+     */
+    public Query queryActivityFeedForUser(String userId) {
+        Query q = queryEntitiesRequest(HttpMethod.GET, null, null,
+                organizationId, applicationId, "users", userId, "feed");
+        return q;
+    }
+
+    /**
+     * Posts an activity to a user. Activity must already be created.
+     * 
+     * @param userId
+     * @param activity
+     * @return
+     */
+    public ApiResponse postUserActivity(String userId, Activity activity) {
+        return apiRequest(HttpMethod.POST, null, activity,  organizationId, applicationId, "users",
+                userId, "activities");
+    }
+
+    /**
+     * Creates and posts an activity to a user.
+     * 
+     * @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(verb, title, content,
+                category, user, object, objectType, objectName, objectContent);
+        return postUserActivity(user.getUuid().toString(), activity);
+    }
+
+    /**
+     * Posts an activity to a group. Activity must already be created.
+     * 
+     * @param userId
+     * @param activity
+     * @return
+     */
+    public ApiResponse postGroupActivity(String groupId, Activity activity) {
+        return apiRequest(HttpMethod.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(verb, title, content,
+                category, user, object, objectType, objectName, objectContent);
+        return postGroupActivity(groupId, activity);
+    }
+
+    /**
+     * 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(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.
+     * 
+     * @param userId
+     * @return
+     */
+    public Query queryActivity() {
+        Query q = queryEntitiesRequest(HttpMethod.GET, null, null,
+               organizationId, applicationId, "activities");
+        return q;
+    }
+
+    
+
+    /**
+     * Get a group's activity feed. Returned as a query to ease paging.
+     * 
+     * @param userId
+     * @return
+     */
+    public Query queryActivityFeedForGroup(String groupId) {
+        Query q = queryEntitiesRequest(HttpMethod.GET, null, null,
+                organizationId,  applicationId, "groups", groupId, "feed");
+        return q;
+    }
+
+    /**
+     * 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.
+     * 
+     * @param method
+     * @param params
+     * @param data
+     * @param segments
+     * @return
+     */
+    public Query queryEntitiesRequest(HttpMethod method,
+            Map<String, Object> params, Object data, String... segments) {
+        ApiResponse response = apiRequest(method, params, data, segments);
+        return new EntityQuery(response, method, params, data, segments);
+    }
+
+    /**
+     * Perform a query of the users collection.
+     * 
+     * @return
+     */
+    public Query queryUsers() {
+        Query q = queryEntitiesRequest(HttpMethod.GET, null, null,
+                organizationId,  applicationId, "users");
+        return q;
+    }
+
+    /**
+     * Perform a query of the users collection using the provided query command.
+     * For example: "name contains 'ed'".
+     * 
+     * @param ql
+     * @return
+     */
+    public Query queryUsers(String ql) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("ql", ql);
+        Query q = queryEntitiesRequest(HttpMethod.GET, params, null,organizationId,
+                applicationId, "users");
+        return q;
+    }
+
+    /**
+     * Perform a query of the users collection within the specified distance of
+     * the specified location and optionally using the provided query command.
+     * For example: "name contains 'ed'".
+     * 
+     * @param distance
+     * @param location
+     * @param ql
+     * @return
+     */
+    public Query queryUsersWithinLocation(float distance, float lattitude,
+            float longitude, String ql) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("ql",
+                this.makeLocationQL(distance, lattitude, longitude, ql));
+        Query q = queryEntitiesRequest(HttpMethod.GET, params, null, organizationId,
+                applicationId, "users");
+        return q;
+    }
+
+    /**
+     * Queries the users for the specified group.
+     * 
+     * @param groupId
+     * @return
+     */
+    public Query queryUsersForGroup(String groupId) {
+        Query q = queryEntitiesRequest(HttpMethod.GET, null, null, organizationId,
+                applicationId, "groups", groupId, "users");
+        return q;
+    }
+
+    /**
+     * Adds a user to the specified groups.
+     * 
+     * @param userId
+     * @param groupId
+     * @return
+     */
+    public ApiResponse addUserToGroup(String userId, String groupId) {
+        return apiRequest(HttpMethod.POST, null, null, organizationId,  applicationId, "groups",
+                groupId, "users", userId);
+    }
+
+    /**
+     * Creates a group with the specified group path. Group paths can be slash
+     * ("/") delimited like file paths for hierarchical group relationships.
+     * 
+     * @param groupPath
+     * @return
+     */
+    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
+     * @param groupTitle
+     * @return
+     */
+    public ApiResponse createGroup(String groupPath, String groupTitle) {
+     return createGroup(groupPath, groupTitle, null);  
+    }
+    
+    /**
+     * Create a group with a path, title and name
+     * @param groupPath
+     * @param groupTitle
+     * @param groupName
+     * @return
+     */
+    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(HttpMethod.POST, null, data,  organizationId, applicationId, "groups");
+    }
+    
+    /**
+     * Perform a query of the users collection using the provided query command.
+     * For example: "name contains 'ed'".
+     * 
+     * @param ql
+     * @return
+     */
+    public Query queryGroups(String ql) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("ql", ql);
+        Query q = queryEntitiesRequest(HttpMethod.GET, params, null, organizationId,
+                applicationId, "groups");
+        return q;
+    }
+
+    
+
+    /**
+     * Connect two entities together.
+     * 
+     * @param connectingEntityType
+     * @param connectingEntityId
+     * @param connectionType
+     * @param connectedEntityId
+     * @return
+     */
+    public ApiResponse connectEntities(String connectingEntityType,
+            String connectingEntityId, String connectionType,
+            String connectedEntityId) {
+        return apiRequest(HttpMethod.POST, null, null,  organizationId, applicationId,
+                connectingEntityType, connectingEntityId, connectionType,
+                connectedEntityId);
+    }
+
+    /**
+     * Disconnect two entities.
+     * 
+     * @param connectingEntityType
+     * @param connectingEntityId
+     * @param connectionType
+     * @param connectedEntityId
+     * @return
+     */
+    public ApiResponse disconnectEntities(String connectingEntityType,
+            String connectingEntityId, String connectionType,
+            String connectedEntityId) {
+        return apiRequest(HttpMethod.DELETE, null, null,  organizationId, applicationId,
+                connectingEntityType, connectingEntityId, connectionType,
+                connectedEntityId);
+    }
+
+    /**
+     * Query the connected entities.
+     * 
+     * @param connectingEntityType
+     * @param connectingEntityId
+     * @param connectionType
+     * @param ql
+     * @return
+     */
+    public Query queryEntityConnections(String connectingEntityType,
+            String connectingEntityId, String connectionType, String ql) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("ql", ql);
+        Query q = queryEntitiesRequest(HttpMethod.GET, params, null,
+                organizationId, applicationId, connectingEntityType, connectingEntityId,
+                connectionType);
+        return q;
+    }
+
+    protected String makeLocationQL(float distance, double lattitude,
+            double longitude, String ql) {
+        String within = String.format("within %d of %d , %d", distance,
+                lattitude, longitude);
+        ql = ql == null ? within : within + " and " + ql;
+        return ql;
+    }
+
+    /**
+     * Query the connected entities within distance of a specific point.
+     * 
+     * @param connectingEntityType
+     * @param connectingEntityId
+     * @param connectionType
+     * @param distance
+     * @param latitude
+     * @param longitude
+     * @return
+     */
+    public Query queryEntityConnectionsWithinLocation(
+            String connectingEntityType, String connectingEntityId,
+            String connectionType, float distance, float lattitude,
+            float longitude, String ql) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("ql", makeLocationQL(distance, lattitude, longitude, ql));
+        Query q = queryEntitiesRequest(HttpMethod.GET, params, null, organizationId,
+                applicationId, connectingEntityType, connectingEntityId,
+                connectionType);
+        return q;
+    }
+
+    public interface Query {
+
+        public ApiResponse getResponse();
+
+        public boolean more();
+
+        public Query next();
+
+    }
+
+    /**
+     * Query object
+     * 
+     */
+    private class EntityQuery implements Query {
+        final HttpMethod method;
+        final Map<String, Object> params;
+        final Object data;
+        final String[] segments;
+        final ApiResponse response;
+
+        private EntityQuery(ApiResponse response, HttpMethod method,
+                Map<String, Object> params, Object data, String[] segments) {
+            this.response = response;
+            this.method = method;
+            this.params = params;
+            this.data = data;
+            this.segments = segments;
+        }
+
+        private EntityQuery(ApiResponse response, EntityQuery q) {
+            this.response = response;
+            method = q.method;
+            params = q.params;
+            data = q.data;
+            segments = q.segments;
+        }
+
+        /**
+         * @return the api response of the last request
+         */
+        public ApiResponse getResponse() {
+            return response;
+        }
+
+        /**
+         * @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
+         * 
+         * @return query that contains results and where to get more from.
+         */
+        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(method, nextParams, data,
+                        segments);
+                return new EntityQuery(nextResponse, this);
+            }
+            return null;
+        }
+
+    }
+
+    private String normalizeQueuePath(String path) {
+        return arrayToDelimitedString(
+                tokenizeToStringArray(path, "/", true, true), "/");
+    }
+
+    public ApiResponse postMessage(String path, Map<String, Object> message) {
+        return apiRequest(HttpMethod.POST, null, message, organizationId,  applicationId,
+                "queues", normalizeQueuePath(path));
+    }
+
+    public ApiResponse postMessage(String path,
+            List<Map<String, Object>> messages) {
+        return apiRequest(HttpMethod.POST, null, messages,  organizationId, applicationId,
+                "queues", normalizeQueuePath(path));
+    }
+
+    public enum QueuePosition {
+        START("start"), END("end"), LAST("last"), CONSUMER("consumer");
+
+        private final String shortName;
+
+        QueuePosition(String shortName) {
+            this.shortName = shortName;
+        }
+
+        static Map<String, QueuePosition> nameMap = new ConcurrentHashMap<String, QueuePosition>();
+
+        static {
+            for (QueuePosition op : EnumSet.allOf(QueuePosition.class)) {
+                if (op.shortName != null) {
+                    nameMap.put(op.shortName, op);
+                }
+            }
+        }
+
+        public static QueuePosition find(String s) {
+            if (s == null) {
+                return null;
+            }
+            return nameMap.get(s);
+        }
+
+        @Override
+        public String toString() {
+            return shortName;
+        }
+    }
+
+    public ApiResponse getMessages(String path, String consumer, UUID last,
+            Long time, Integer prev, Integer next, Integer limit,
+            QueuePosition pos, Boolean update, Boolean sync) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        if (consumer != null) {
+            params.put("consumer", consumer);
+        }
+        if (last != null) {
+            params.put("last", last);
+        }
+        if (time != null) {
+            params.put("time", time);
+        }
+        if (prev != null) {
+            params.put("prev", prev);
+        }
+        if (next != null) {
+            params.put("next", next);
+        }
+        if (limit != null) {
+            params.put("limit", limit);
+        }
+        if (pos != null) {
+            params.put("pos", pos.toString());
+        }
+        if (update != null) {
+            params.put("update", update);
+        }
+        if (sync != null) {
+            params.put("synchronized", sync);
+        }
+        return apiRequest(HttpMethod.GET, params, null,  organizationId, applicationId,
+                "queues", normalizeQueuePath(path));
+    }
+
+    public ApiResponse addSubscriber(String publisherQueue,
+            String subscriberQueue) {
+        return apiRequest(HttpMethod.POST, null, null, organizationId,  applicationId, "queues",
+                normalizeQueuePath(publisherQueue), "subscribers",
+                normalizeQueuePath(subscriberQueue));
+    }
+
+    public ApiResponse removeSubscriber(String publisherQueue,
+            String subscriberQueue) {
+        return apiRequest(HttpMethod.DELETE, null, null, organizationId,  applicationId,
+                "queues", normalizeQueuePath(publisherQueue), "subscribers",
+                normalizeQueuePath(subscriberQueue));
+    }
+
+    private class QueueQuery implements Query {
+        final HttpMethod method;
+        final Map<String, Object> params;
+        final Object data;
+        final String queuePath;
+        final ApiResponse response;
+
+        private QueueQuery(ApiResponse response, HttpMethod method,
+                Map<String, Object> params, Object data, String queuePath) {
+            this.response = response;
+            this.method = method;
+            this.params = params;
+            this.data = data;
+            this.queuePath = normalizeQueuePath(queuePath);
+        }
+
+        private QueueQuery(ApiResponse response, QueueQuery q) {
+            this.response = response;
+            method = q.method;
+            params = q.params;
+            data = q.data;
+            queuePath = q.queuePath;
+        }
+
+        /**
+         * @return the api response of the last request
+         */
+        public ApiResponse getResponse() {
+            return response;
+        }
+
+        /**
+         * @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
+         * 
+         * @return query that contains results and where to get more from.
+         */
+        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("start", response.getCursor());
+                ApiResponse nextResponse = apiRequest(method, nextParams, data,
+                        queuePath);
+                return new QueueQuery(nextResponse, this);
+            }
+            return null;
+        }
+
+    }
+
+    public Query queryQueuesRequest(HttpMethod method,
+            Map<String, Object> params, Object data, String queuePath) {
+        ApiResponse response = apiRequest(method, params, data, queuePath);
+        return new QueueQuery(response, method, params, data, queuePath);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c08a2791/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Activity.java
----------------------------------------------------------------------
diff --git a/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Activity.java b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Activity.java
new file mode 100644
index 0000000..c4989de
--- /dev/null
+++ b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Activity.java
@@ -0,0 +1,626 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.usergrid.java.client.entities;
+
+
+import static org.usergrid.java.client.utils.JsonUtils.getStringProperty;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.UUID;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion;
+
+/**
+ * An entity type for representing activity stream actions. These are similar to
+ * the more generic message entity type except provide the necessary properties
+ * for supporting activity stream implementations.
+ * 
+ * @see http://activitystrea.ms/specs/json/1.0/
+ */
+public class Activity extends Entity {
+
+    public static final String ENTITY_TYPE = "activity";
+
+    public static final String PROP_ACTOR = "actor";
+
+    public static final String VERB_ADD = "add";
+    public static final String VERB_CANCEL = "cancel";
+    public static final String VERB_CHECKIN = "checkin";
+    public static final String VERB_DELETE = "delete";
+    public static final String VERB_FAVORITE = "favorite";
+    public static final String VERB_FOLLOW = "follow";
+    public static final String VERB_GIVE = "give";
+    public static final String VERB_IGNORE = "ignore";
+    public static final String VERB_INVITE = "invite";
+    public static final String VERB_JOIN = "join";
+    public static final String VERB_LEAVE = "leave";
+    public static final String VERB_LIKE = "like";
+    public static final String VERB_MAKE_FRIEND = "make-friend";
+    public static final String VERB_PLAY = "play";
+    public static final String VERB_POST = "post";
+    public static final String VERB_RECEIVE = "receive";
+    public static final String VERB_REMOVE = "remove";
+    public static final String VERB_REMOVE_FRIEND = "remove-friend";
+    public static final String VERB_REQUEST_FRIEND = "request-friend";
+    public static final String VERB_RSVP_MAYBE = "rsvp-maybe";
+    public static final String VERB_RSVP_NO = "rsvp-no";
+    public static final String VERB_RSVP_YES = "rsvp-yes";
+    public static final String VERB_SAVE = "save";
+    public static final String VERB_SHARE = "share";
+    public static final String VERB_STOP_FOLLOWING = "stop-following";
+    public static final String VERB_TAG = "tag";
+    public static final String VERB_UNFAVORITE = "unfavorite";
+    public static final String VERB_UNLIKE = "unlike";
+    public static final String VERB_UNSAVE = "unsave";
+    public static final String VERB_UPDATE = "update";
+
+    public static final String OBJECT_TYPE_ARTICLE = "article";
+    public static final String OBJECT_TYPE_AUDIO = "audio";
+    public static final String OBJECT_TYPE_BADGE = "badge";
+    public static final String OBJECT_TYPE_BOOKMARK = "bookmark";
+    public static final String OBJECT_TYPE_COLLECTION = "collection";
+    public static final String OBJECT_TYPE_COMMENT = "comment";
+    public static final String OBJECT_TYPE_EVENT = "event";
+    public static final String OBJECT_TYPE_FILE = "file";
+    public static final String OBJECT_TYPE_GROUP = "group";
+    public static final String OBJECT_TYPE_IMAGE = "image";
+    public static final String OBJECT_TYPE_NOTE = "note";
+    public static final String OBJECT_TYPE_PERSON = "person";
+    public static final String OBJECT_TYPE_PLACE = "place";
+    public static final String OBJECT_TYPE_PRODUCT = "product";
+    public static final String OBJECT_TYPE_QUESTION = "question";
+    public static final String OBJECT_TYPE_REVIEW = "review";
+    public static final String OBJECT_TYPE_SERVICE = "service";
+    public static final String OBJECT_TYPE_VIDEO = "video";
+
+    protected ActivityObject actor;
+
+    protected String content;
+
+    protected ActivityObject generator;
+
+    protected MediaLink icon;
+
+    protected String category;
+
+    protected String verb;
+
+    protected Long published;
+
+    protected ActivityObject object;
+
+    // protected
+    // String objectType;
+
+    // protected
+    // String objectEntityType;
+
+    // protected
+    // String objectName;
+
+    protected String title;
+
+    protected Set<String> connections;
+
+    public Activity() {
+        setType("activity");
+    }
+
+    public Activity(UUID id) {
+        this();
+        setUuid(id);
+    }
+
+    public static Activity newActivity(String verb, String title,
+            String content, String category, Entity user, Entity object,
+            String objectType, String objectName, String objectContent){
+
+        Activity activity = new Activity();
+        activity.setVerb(verb);
+        activity.setCategory(category);
+        activity.setContent(content);
+        activity.setTitle(title);
+        
+        ActivityObject actor = new ActivityObject();
+        actor.setObjectType("person");
+        
+        if (user != null) {
+            actor.setDisplayName(getStringProperty(user.properties, "name"));
+            actor.setEntityType(user.getType());
+            actor.setUuid(user.getUuid());
+        }
+        
+        activity.setActor(actor);
+
+        ActivityObject obj = new ActivityObject();
+        obj.setDisplayName(objectName);
+        obj.setObjectType(objectType);
+        if (object != null) {
+            obj.setEntityType(object.getType());
+            obj.setUuid(object.getUuid());
+        }
+        if (objectContent != null) {
+            obj.setContent(objectContent);
+        } else {
+            obj.setContent(content);
+        }
+        activity.setObject(obj);
+
+        return activity;
+    }
+
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public ActivityObject getActor() {
+        return actor;
+    }
+
+    public void setActor(ActivityObject actor) {
+        this.actor = actor;
+    }
+
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public ActivityObject getGenerator() {
+        return generator;
+    }
+
+    public void setGenerator(ActivityObject generator) {
+        this.generator = generator;
+    }
+
+    /*
+     * @JsonSerialize(include = Inclusion.NON_NULL) public String getActorName()
+     * { return actorName; }
+     * 
+     * public void setActorName(String actorName) { this.actorName = actorName;
+     * }
+     */
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public String getCategory() {
+        return category;
+    }
+
+    public void setCategory(String category) {
+        this.category = category;
+    }
+
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public String getVerb() {
+        return verb;
+    }
+
+    public void setVerb(String verb) {
+        this.verb = verb;
+    }
+
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public Long getPublished() {
+        return published;
+    }
+
+    public void setPublished(Long published) {
+        this.published = published;
+    }
+
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public ActivityObject getObject() {
+        return object;
+    }
+
+    public void setObject(ActivityObject object) {
+        this.object = object;
+    }
+
+    /*
+     * @JsonSerialize(include = Inclusion.NON_NULL) public String
+     * getObjectType() { return objectType; }
+     * 
+     * public void setObjectType(String objectType) { this.objectType =
+     * objectType; }
+     * 
+     * @JsonSerialize(include = Inclusion.NON_NULL) public String
+     * getObjectEntityType() { return objectEntityType; }
+     * 
+     * public void setObjectEntityType(String objectEntityType) {
+     * this.objectEntityType = objectEntityType; }
+     * 
+     * @JsonSerialize(include = Inclusion.NON_NULL) public String
+     * getObjectName() { return objectName; }
+     * 
+     * public void setObjectName(String objectName) { this.objectName =
+     * objectName; }
+     */
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public MediaLink getIcon() {
+        return icon;
+    }
+
+    public void setIcon(MediaLink icon) {
+        this.icon = icon;
+    }
+
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public Set<String> getConnections() {
+        return connections;
+    }
+
+    public void setConnections(Set<String> connections) {
+        this.connections = connections;
+    }
+
+    @XmlRootElement
+    static public class MediaLink {
+
+        int duration;
+
+        int height;
+
+        String url;
+
+        int width;
+
+        protected Map<String, Object> dynamic_properties = new TreeMap<String, Object>(
+                String.CASE_INSENSITIVE_ORDER);
+
+        public MediaLink() {
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public int getDuration() {
+            return duration;
+        }
+
+        public void setDuration(int duration) {
+            this.duration = duration;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public int getHeight() {
+            return height;
+        }
+
+        public void setHeight(int height) {
+            this.height = height;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getUrl() {
+            return url;
+        }
+
+        public void setUrl(String url) {
+            this.url = url;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public int getWidth() {
+            return width;
+        }
+
+        public void setWidth(int width) {
+            this.width = width;
+        }
+
+        @JsonAnySetter
+        public void setDynamicProperty(String key, Object value) {
+            dynamic_properties.put(key, value);
+        }
+
+        @JsonAnyGetter
+        public Map<String, Object> getDynamicProperties() {
+            return dynamic_properties;
+        }
+
+        @Override
+        public String toString() {
+            return "MediaLink [duration=" + duration + ", height=" + height
+                    + ", url=" + url + ", width=" + width
+                    + ", dynamic_properties=" + dynamic_properties + "]";
+        }
+
+    }
+
+    @XmlRootElement
+    static public class ActivityObject {
+
+        ActivityObject[] attachments;
+
+        ActivityObject author;
+
+        String content;
+
+        String displayName;
+
+        String[] downstreamDuplicates;
+
+        String id;
+
+        MediaLink image;
+
+        String objectType;
+
+        Date published;
+
+        String summary;
+
+        String updated;
+
+        String upstreamDuplicates;
+
+        String url;
+
+        UUID uuid;
+
+        String entityType;
+
+        protected Map<String, Object> dynamic_properties = new TreeMap<String, Object>(
+                String.CASE_INSENSITIVE_ORDER);
+
+        public ActivityObject() {
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public ActivityObject[] getAttachments() {
+            return attachments;
+        }
+
+        public void setAttachments(ActivityObject[] attachments) {
+            this.attachments = attachments;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public ActivityObject getAuthor() {
+            return author;
+        }
+
+        public void setAuthor(ActivityObject author) {
+            this.author = author;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getContent() {
+            return content;
+        }
+
+        public void setContent(String content) {
+            this.content = content;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getDisplayName() {
+            return displayName;
+        }
+
+        public void setDisplayName(String displayName) {
+            this.displayName = displayName;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String[] getDownstreamDuplicates() {
+            return downstreamDuplicates;
+        }
+
+        public void setDownstreamDuplicates(String[] downstreamDuplicates) {
+            this.downstreamDuplicates = downstreamDuplicates;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getId() {
+            return id;
+        }
+
+        public void setId(String id) {
+            this.id = id;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public MediaLink getImage() {
+            return image;
+        }
+
+        public void setImage(MediaLink image) {
+            this.image = image;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getObjectType() {
+            return objectType;
+        }
+
+        public void setObjectType(String objectType) {
+            this.objectType = objectType;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public Date getPublished() {
+            return published;
+        }
+
+        public void setPublished(Date published) {
+            this.published = published;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getSummary() {
+            return summary;
+        }
+
+        public void setSummary(String summary) {
+            this.summary = summary;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getUpdated() {
+            return updated;
+        }
+
+        public void setUpdated(String updated) {
+            this.updated = updated;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getUpstreamDuplicates() {
+            return upstreamDuplicates;
+        }
+
+        public void setUpstreamDuplicates(String upstreamDuplicates) {
+            this.upstreamDuplicates = upstreamDuplicates;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getUrl() {
+            return url;
+        }
+
+        public void setUrl(String url) {
+            this.url = url;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public UUID getUuid() {
+            return uuid;
+        }
+
+        public void setUuid(UUID uuid) {
+            this.uuid = uuid;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getEntityType() {
+            return entityType;
+        }
+
+        public void setEntityType(String entityType) {
+            this.entityType = entityType;
+        }
+
+        @JsonAnySetter
+        public void setDynamicProperty(String key, Object value) {
+            dynamic_properties.put(key, value);
+        }
+
+        @JsonAnyGetter
+        public Map<String, Object> getDynamicProperties() {
+            return dynamic_properties;
+        }
+
+        @Override
+        public String toString() {
+            return "ActivityObject [attachments="
+                    + Arrays.toString(attachments) + ", author=" + author
+                    + ", content=" + content + ", displayName=" + displayName
+                    + ", downstreamDuplicates="
+                    + Arrays.toString(downstreamDuplicates) + ", id=" + id
+                    + ", image=" + image + ", objectType=" + objectType
+                    + ", published=" + published + ", summary=" + summary
+                    + ", updated=" + updated + ", upstreamDuplicates="
+                    + upstreamDuplicates + ", url=" + url + ", uuid=" + uuid
+                    + ", entityType=" + entityType + ", dynamic_properties="
+                    + dynamic_properties + "]";
+        }
+
+    }
+
+    @XmlRootElement
+    static public class ActivityCollection {
+
+        int totalItems;
+
+        ActivityObject[] items;
+
+        String url;
+
+        protected Map<String, Object> dynamic_properties = new TreeMap<String, Object>(
+                String.CASE_INSENSITIVE_ORDER);
+
+        public ActivityCollection() {
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public int getTotalItems() {
+            return totalItems;
+        }
+
+        public void setTotalItems(int totalItems) {
+            this.totalItems = totalItems;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public ActivityObject[] getItems() {
+            return items;
+        }
+
+        public void setItems(ActivityObject[] items) {
+            this.items = items;
+        }
+
+        @JsonSerialize(include = Inclusion.NON_NULL)
+        public String getUrl() {
+            return url;
+        }
+
+        public void setUrl(String url) {
+            this.url = url;
+        }
+
+        @JsonAnySetter
+        public void setDynamicProperty(String key, Object value) {
+            dynamic_properties.put(key, value);
+        }
+
+        @JsonAnyGetter
+        public Map<String, Object> getDynamicProperties() {
+            return dynamic_properties;
+        }
+
+        @Override
+        public String toString() {
+            return "ActivityCollection [totalItems=" + totalItems + ", items="
+                    + Arrays.toString(items) + ", url=" + url
+                    + ", dynamic_properties=" + dynamic_properties + "]";
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c08a2791/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Device.java
----------------------------------------------------------------------
diff --git a/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Device.java b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Device.java
new file mode 100644
index 0000000..075733a
--- /dev/null
+++ b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Device.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.usergrid.java.client.entities;
+
+import static com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion.NON_NULL;
+import static org.usergrid.java.client.utils.JsonUtils.getStringProperty;
+import static org.usergrid.java.client.utils.JsonUtils.setStringProperty;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+public class Device extends Entity {
+
+	public final static String ENTITY_TYPE = "device";
+
+	public final static String PROPERTY_NAME = "name";
+
+	public Device() {
+		super();
+		setType(ENTITY_TYPE);
+	}
+
+	public Device(Entity entity) {
+		super();
+		properties = entity.properties;
+		setType(ENTITY_TYPE);
+	}
+
+	@Override
+	@JsonIgnore
+	public String getNativeType() {
+		return ENTITY_TYPE;
+	}
+
+	@Override
+	@JsonIgnore
+	public List<String> getPropertyNames() {
+		List<String> properties = super.getPropertyNames();
+		properties.add(PROPERTY_NAME);
+		return properties;
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getName() {
+		return getStringProperty(properties, PROPERTY_NAME);
+	}
+
+	public void setName(String name) {
+		setStringProperty(properties, PROPERTY_NAME, name);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c08a2791/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Entity.java
----------------------------------------------------------------------
diff --git a/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Entity.java b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Entity.java
new file mode 100644
index 0000000..6bce0b6
--- /dev/null
+++ b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Entity.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.usergrid.java.client.entities;
+
+import static org.usergrid.java.client.utils.JsonUtils.getStringProperty;
+import static org.usergrid.java.client.utils.JsonUtils.getUUIDProperty;
+import static org.usergrid.java.client.utils.JsonUtils.setStringProperty;
+import static org.usergrid.java.client.utils.JsonUtils.*;
+import static org.usergrid.java.client.utils.MapUtils.newMapWithoutKeys;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class Entity {
+
+    public final static String PROPERTY_UUID = "uuid";
+    public final static String PROPERTY_TYPE = "type";
+
+    protected Map<String, JsonNode> properties = new HashMap<String, JsonNode>();
+
+    public static Map<String, Class<? extends Entity>> CLASS_FOR_ENTITY_TYPE = new HashMap<String, Class<? extends Entity>>();
+    static {
+        CLASS_FOR_ENTITY_TYPE.put(User.ENTITY_TYPE, User.class);
+    }
+
+    public Entity() {
+    }
+
+    public Entity(String type) {
+        setType(type);
+    }
+
+    @JsonIgnore
+    public String getNativeType() {
+        return getType();
+    }
+
+    @JsonIgnore
+    public List<String> getPropertyNames() {
+        List<String> properties = new ArrayList<String>();
+        properties.add(PROPERTY_TYPE);
+        properties.add(PROPERTY_UUID);
+        return properties;
+    }
+
+    public String getType() {
+        return getStringProperty(properties, PROPERTY_TYPE);
+    }
+
+    public void setType(String type) {
+        setStringProperty(properties, PROPERTY_TYPE, type);
+    }
+
+    public UUID getUuid() {
+        return getUUIDProperty(properties, PROPERTY_UUID);
+    }
+
+    public void setUuid(UUID uuid) {
+        setUUIDProperty(properties, PROPERTY_UUID, uuid);
+    }
+
+    @JsonAnyGetter
+    public Map<String, JsonNode> getProperties() {
+        return newMapWithoutKeys(properties, getPropertyNames());
+    }
+
+    @JsonAnySetter
+    public void setProperty(String name, JsonNode value) {
+        if (value == null) {
+            properties.remove(name);
+        } else {
+            properties.put(name, value);
+        }
+    }
+
+  
+    /**
+     * Set the property
+     * 
+     * @param name
+     * @param value
+     */
+    public void setProperty(String name, String value) {
+        setStringProperty(properties, name, value);
+    }
+
+    /**
+     * Set the property
+     * 
+     * @param name
+     * @param value
+     */
+    public void setProperty(String name, boolean value) {
+        setBooleanProperty(properties, name, value);
+    }
+
+    /**
+     * Set the property
+     * 
+     * @param name
+     * @param value
+     */
+    public void setProperty(String name, long value) {
+        setLongProperty(properties, name, value);
+    }
+
+    /**
+     * Set the property
+     * 
+     * @param name
+     * @param value
+     */
+    public void setProperty(String name, int value) {
+        setProperty(name, (long) value);
+    }
+
+    /**
+     * Set the property
+     * 
+     * @param name
+     * @param value
+     */
+    public void setProperty(String name, float value) {
+        setFloatProperty(properties, name, value);
+    }
+
+    @Override
+    public String toString() {
+        return toJsonString(this);
+    }
+
+    public <T extends Entity> T toType(Class<T> t) {
+        return toType(this, t);
+    }
+
+    public static <T extends Entity> T toType(Entity entity, Class<T> t) {
+        if (entity == null) {
+            return null;
+        }
+        T newEntity = null;
+        if (entity.getClass().isAssignableFrom(t)) {
+            try {
+                newEntity = (t.newInstance());
+                if ((newEntity.getNativeType() != null)
+                        && newEntity.getNativeType().equals(entity.getType())) {
+                    newEntity.properties = entity.properties;
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return newEntity;
+    }
+
+    public static <T extends Entity> List<T> toType(List<Entity> entities,
+            Class<T> t) {
+        List<T> l = new ArrayList<T>(entities != null ? entities.size() : 0);
+        if (entities != null) {
+            for (Entity entity : entities) {
+                T newEntity = entity.toType(t);
+                if (newEntity != null) {
+                    l.add(newEntity);
+                }
+            }
+        }
+        return l;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c08a2791/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Group.java
----------------------------------------------------------------------
diff --git a/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Group.java b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Group.java
new file mode 100644
index 0000000..334d74a
--- /dev/null
+++ b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Group.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.usergrid.java.client.entities;
+
+import static com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion.NON_NULL;
+import static org.usergrid.java.client.utils.JsonUtils.getStringProperty;
+import static org.usergrid.java.client.utils.JsonUtils.setStringProperty;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+public class Group extends Entity {
+
+	public final static String ENTITY_TYPE = "group";
+
+	public final static String PROPERTY_PATH = "path";
+	public final static String PROPERTY_TITLE = "title";
+
+	public Group() {
+		super();
+		setType(ENTITY_TYPE);
+	}
+
+	public Group(Entity entity) {
+		super();
+		properties = entity.properties;
+		setType(ENTITY_TYPE);
+	}
+
+	@Override
+	@JsonIgnore
+	public String getNativeType() {
+		return ENTITY_TYPE;
+	}
+
+	@Override
+	@JsonIgnore
+	public List<String> getPropertyNames() {
+		List<String> properties = super.getPropertyNames();
+		properties.add(PROPERTY_PATH);
+		properties.add(PROPERTY_TITLE);
+		return properties;
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getPath() {
+		return getStringProperty(properties, PROPERTY_PATH);
+	}
+
+	public void setPath(String path) {
+		setStringProperty(properties, PROPERTY_PATH, path);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getTitle() {
+		return getStringProperty(properties, PROPERTY_TITLE);
+	}
+
+	public void setTitle(String title) {
+		setStringProperty(properties, PROPERTY_TITLE, title);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c08a2791/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Message.java
----------------------------------------------------------------------
diff --git a/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Message.java b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Message.java
new file mode 100644
index 0000000..170f705
--- /dev/null
+++ b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/Message.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.usergrid.java.client.entities;
+
+import static com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion.NON_NULL;
+import static org.usergrid.java.client.utils.JsonUtils.getBooleanProperty;
+import static org.usergrid.java.client.utils.JsonUtils.getLongProperty;
+import static org.usergrid.java.client.utils.JsonUtils.getStringProperty;
+import static org.usergrid.java.client.utils.JsonUtils.getUUIDProperty;
+import static org.usergrid.java.client.utils.JsonUtils.setBooleanProperty;
+import static org.usergrid.java.client.utils.JsonUtils.setLongProperty;
+import static org.usergrid.java.client.utils.JsonUtils.setStringProperty;
+import static org.usergrid.java.client.utils.JsonUtils.setUUIDProperty;
+
+import java.util.List;
+import java.util.UUID;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion;
+
+public class Message extends Entity {
+
+	public static final String ENTITY_TYPE = "message";
+
+	public static final String PROPERTY_CORRELATION_ID = "correlation_id";
+	public static final String PROPERTY_DESTINATION = "destination";
+	public static final String PROPERTY_REPLY_TO = "reply_to";
+	public static final String PROPERTY_TIMESTAMP = "timestamp";
+	public static final String PROPERTY_TYPE = "type";
+	public static final String PROPERTY_CATEGORY = "category";
+	public static final String PROPERTY_INDEXED = "indexed";
+	public static final String PROPERTY_PERSISTENT = "persistent";
+
+	public Message() {
+		super();
+		setType(ENTITY_TYPE);
+	}
+
+	public Message(Entity entity) {
+		super();
+		properties = entity.properties;
+		setType(ENTITY_TYPE);
+	}
+
+	@Override
+	@JsonIgnore
+	public String getNativeType() {
+		return ENTITY_TYPE;
+	}
+
+	@Override
+	@JsonIgnore
+	public List<String> getPropertyNames() {
+		List<String> properties = super.getPropertyNames();
+		properties.add(PROPERTY_CORRELATION_ID);
+		properties.add(PROPERTY_DESTINATION);
+		properties.add(PROPERTY_REPLY_TO);
+		properties.add(PROPERTY_TIMESTAMP);
+		properties.add(PROPERTY_CATEGORY);
+		properties.add(PROPERTY_INDEXED);
+		properties.add(PROPERTY_PERSISTENT);
+		return properties;
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	@JsonProperty(PROPERTY_CORRELATION_ID)
+	public UUID getCorrelationId() {
+		return getUUIDProperty(properties, PROPERTY_CORRELATION_ID);
+	}
+
+	@JsonProperty(PROPERTY_CORRELATION_ID)
+	public void setCorrelationId(UUID uuid) {
+		setUUIDProperty(properties, PROPERTY_CORRELATION_ID, uuid);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getDestination() {
+		return getStringProperty(properties, PROPERTY_DESTINATION);
+	}
+
+	public void setDestination(String destination) {
+		setStringProperty(properties, PROPERTY_DESTINATION, destination);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	@JsonProperty(PROPERTY_REPLY_TO)
+	public String getReplyTo() {
+		return getStringProperty(properties, PROPERTY_DESTINATION);
+	}
+
+	@JsonProperty(PROPERTY_REPLY_TO)
+	public void setReplyTo(String replyTo) {
+		setStringProperty(properties, PROPERTY_DESTINATION, replyTo);
+	}
+
+	@JsonSerialize(include = Inclusion.NON_NULL)
+	public Long getTimestamp() {
+		return getLongProperty(properties, PROPERTY_TIMESTAMP);
+	}
+
+	public void setTimestamp(Long timestamp) {
+		setLongProperty(properties, PROPERTY_TIMESTAMP, timestamp);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getCategory() {
+		return getStringProperty(properties, PROPERTY_CATEGORY);
+	}
+
+	public void setCategory(String category) {
+		setStringProperty(properties, PROPERTY_CATEGORY, category);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public Boolean isIndexed() {
+		return getBooleanProperty(properties, PROPERTY_INDEXED);
+	}
+
+	public void setIndexed(Boolean indexed) {
+		setBooleanProperty(properties, PROPERTY_INDEXED, indexed);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public Boolean isPersistent() {
+		return getBooleanProperty(properties, PROPERTY_INDEXED);
+	}
+
+	public void setPersistent(Boolean persistent) {
+		setBooleanProperty(properties, PROPERTY_INDEXED, persistent);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c08a2791/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/User.java
----------------------------------------------------------------------
diff --git a/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/User.java b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/User.java
new file mode 100644
index 0000000..b6cd22b
--- /dev/null
+++ b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/entities/User.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.usergrid.java.client.entities;
+
+import static com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion.NON_NULL;
+import static org.usergrid.java.client.utils.JsonUtils.getBooleanProperty;
+import static org.usergrid.java.client.utils.JsonUtils.getStringProperty;
+import static org.usergrid.java.client.utils.JsonUtils.setBooleanProperty;
+import static org.usergrid.java.client.utils.JsonUtils.setStringProperty;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+public class User extends Entity {
+
+	public final static String ENTITY_TYPE = "user";
+
+	public final static String PROPERTY_USERNAME = "username";
+	public final static String PROPERTY_EMAIL = "email";
+	public final static String PROPERTY_NAME = "name";
+	public final static String PROPERTY_FIRSTNAME = "firstname";
+	public final static String PROPERTY_MIDDLENAME = "middlename";
+	public final static String PROPERTY_LASTNAME = "lastname";
+	public final static String PROPERTY_ACTIVATED = "activated";
+	public final static String PROPERTY_PICTURE = "picture";
+	public final static String PROPERTY_DISABLED = "disabled";
+
+	public User() {
+		super();
+		setType(ENTITY_TYPE);
+	}
+
+	public User(Entity entity) {
+		super();
+		properties = entity.properties;
+		setType(ENTITY_TYPE);
+	}
+
+	@Override
+	@JsonIgnore
+	public String getNativeType() {
+		return ENTITY_TYPE;
+	}
+
+	@Override
+	@JsonIgnore
+	public List<String> getPropertyNames() {
+		List<String> properties = super.getPropertyNames();
+		properties.add(PROPERTY_USERNAME);
+		properties.add(PROPERTY_EMAIL);
+		properties.add(PROPERTY_NAME);
+		properties.add(PROPERTY_FIRSTNAME);
+		properties.add(PROPERTY_MIDDLENAME);
+		properties.add(PROPERTY_LASTNAME);
+		properties.add(PROPERTY_ACTIVATED);
+		properties.add(PROPERTY_PICTURE);
+		properties.add(PROPERTY_DISABLED);
+		return properties;
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getUsername() {
+		return getStringProperty(properties, PROPERTY_USERNAME);
+	}
+
+	public void setUsername(String username) {
+		setStringProperty(properties, PROPERTY_USERNAME, username);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getName() {
+		return getStringProperty(properties, PROPERTY_NAME);
+	}
+
+	public void setName(String name) {
+		setStringProperty(properties, PROPERTY_NAME, name);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getEmail() {
+		return getStringProperty(properties, PROPERTY_EMAIL);
+	}
+
+	public void setEmail(String email) {
+		setStringProperty(properties, PROPERTY_EMAIL, email);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public Boolean isActivated() {
+		return getBooleanProperty(properties, PROPERTY_ACTIVATED);
+	}
+
+	public void setActivated(Boolean activated) {
+		setBooleanProperty(properties, PROPERTY_ACTIVATED, activated);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public Boolean isDisabled() {
+		return getBooleanProperty(properties, PROPERTY_DISABLED);
+	}
+
+	public void setDisabled(Boolean disabled) {
+		setBooleanProperty(properties, PROPERTY_DISABLED, disabled);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getFirstname() {
+		return getStringProperty(properties, PROPERTY_FIRSTNAME);
+	}
+
+	public void setFirstname(String firstname) {
+		setStringProperty(properties, PROPERTY_FIRSTNAME, firstname);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getMiddlename() {
+		return getStringProperty(properties, PROPERTY_MIDDLENAME);
+	}
+
+	public void setMiddlename(String middlename) {
+		setStringProperty(properties, PROPERTY_MIDDLENAME, middlename);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getLastname() {
+		return getStringProperty(properties, PROPERTY_LASTNAME);
+	}
+
+	public void setLastname(String lastname) {
+		setStringProperty(properties, PROPERTY_LASTNAME, lastname);
+	}
+
+	@JsonSerialize(include = NON_NULL)
+	public String getPicture() {
+		return getStringProperty(properties, PROPERTY_PICTURE);
+	}
+
+	public void setPicture(String picture) {
+		setStringProperty(properties, PROPERTY_PICTURE, picture);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c08a2791/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/exception/ClientException.java
----------------------------------------------------------------------
diff --git a/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/exception/ClientException.java b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/exception/ClientException.java
new file mode 100644
index 0000000..834f11a
--- /dev/null
+++ b/sdks/usergrid-java-sdk-0.0.6/src/main/java/org/usergrid/java/client/exception/ClientException.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.usergrid.java.client.exception;
+
+/**
+ * Simple wrapper for client exceptions
+ * @author tnine
+ *
+ */
+public class ClientException extends RuntimeException{
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public ClientException(String message, Throwable cause) {
+        super(message, cause);
+    }
+    
+    
+
+}