http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/UsergridRequest.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/usergrid/java/client/UsergridRequest.java 
b/src/main/java/org/apache/usergrid/java/client/UsergridRequest.java
new file mode 100644
index 0000000..b16783e
--- /dev/null
+++ b/src/main/java/org/apache/usergrid/java/client/UsergridRequest.java
@@ -0,0 +1,205 @@
+/*
+ * 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.apache.usergrid.java.client;
+
+import okhttp3.HttpUrl;
+import okhttp3.MediaType;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import org.apache.usergrid.java.client.UsergridEnums.UsergridHttpMethod;
+import org.apache.usergrid.java.client.auth.UsergridAuth;
+import org.apache.usergrid.java.client.query.UsergridQuery;
+import org.apache.usergrid.java.client.utils.JsonUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+@SuppressWarnings("unused")
+public class UsergridRequest {
+    @NotNull public static final MediaType APPLICATION_JSON_MEDIA_TYPE = 
MediaType.parse("application/json; charset=utf-8");
+
+    @NotNull private UsergridHttpMethod method;
+    @NotNull private String baseUrl;
+    @NotNull private MediaType contentType;
+
+    @Nullable private UsergridQuery query;
+    @Nullable private Map<String, Object> headers;
+    @Nullable private Map<String, Object> parameters;
+    @Nullable private Object data;
+    @Nullable private UsergridAuth auth;
+    @Nullable private String[] pathSegments;
+
+    @NotNull
+    public UsergridHttpMethod getMethod() { return method; }
+    public void setMethod(@NotNull final UsergridHttpMethod method) { 
this.method = method; }
+
+    @NotNull
+    public String getBaseUrl() { return baseUrl; }
+    public void setBaseUrl(@NotNull final String baseUrl) { this.baseUrl = 
baseUrl; }
+
+    @NotNull
+    public MediaType getContentType() { return contentType; }
+    public void setContentType(@NotNull final MediaType contentType) { 
this.contentType = contentType; }
+
+    @Nullable
+    public UsergridQuery getQuery() { return query; }
+    public void setQuery(@Nullable final UsergridQuery query) { this.query = 
query; }
+
+    @Nullable
+    public Map<String,Object> getHeaders() { return headers; }
+    public void setHeaders(@Nullable final Map<String,Object> headers) { 
this.headers = headers; }
+
+    @Nullable
+    public Map<String,Object> getParameters() { return parameters; }
+    public void setParameters(@Nullable final Map<String,Object> parameters) { 
this.parameters = parameters; }
+
+    @Nullable
+    public Object getData() { return data; }
+    public void setData(@Nullable final Object data) { this.data = data; }
+
+    @Nullable
+    public UsergridAuth getAuth() { return auth; }
+    public void setAuth(@Nullable final UsergridAuth auth) { this.auth = auth; 
}
+
+    @Nullable
+    public String[] getPathSegments() { return pathSegments; }
+    public void setPathSegments(@Nullable final String[] pathSegments) { 
this.pathSegments = pathSegments; }
+
+    private UsergridRequest() {}
+
+    public UsergridRequest(@NotNull final UsergridHttpMethod method,
+                           @NotNull final MediaType contentType,
+                           @NotNull final String url,
+                           @Nullable final UsergridQuery query,
+                           @Nullable final UsergridAuth auth,
+                           @Nullable final String... pathSegments) {
+        this.method = method;
+        this.contentType = contentType;
+        this.baseUrl = url;
+        this.query = query;
+        this.auth = auth;
+        this.pathSegments = pathSegments;
+    }
+
+    public UsergridRequest(@NotNull final UsergridHttpMethod method,
+                           @NotNull final MediaType contentType,
+                           @NotNull final String url,
+                           @Nullable final UsergridAuth auth,
+                           @Nullable final String... pathSegments) {
+        this.method = method;
+        this.contentType = contentType;
+        this.baseUrl = url;
+        this.auth = auth;
+        this.pathSegments = pathSegments;
+    }
+
+    public UsergridRequest(@NotNull final UsergridHttpMethod method,
+                           @NotNull final MediaType contentType,
+                           @NotNull final String url,
+                           @Nullable final Map<String, Object> params,
+                           @Nullable final Object data,
+                           @Nullable final UsergridAuth auth,
+                           @Nullable final String... pathSegments) {
+        this.method = method;
+        this.contentType = contentType;
+        this.baseUrl = url;
+        this.parameters = params;
+        this.data = data;
+        this.headers = null;
+        this.query = null;
+        this.auth = auth;
+        this.pathSegments = pathSegments;
+    }
+
+    public UsergridRequest(@NotNull final UsergridHttpMethod method,
+                           @NotNull final MediaType contentType,
+                           @NotNull final String url,
+                           @Nullable final Map<String, Object> params,
+                           @Nullable final Object data,
+                           @Nullable final Map<String, Object> headers,
+                           @Nullable final UsergridQuery query,
+                           @Nullable final UsergridAuth auth,
+                           @Nullable final String... pathSegments) {
+        this.method = method;
+        this.contentType = contentType;
+        this.baseUrl = url;
+        this.parameters = params;
+        this.data = data;
+        this.headers = headers;
+        this.query = query;
+        this.auth = auth;
+        this.pathSegments = pathSegments;
+    }
+
+    @NotNull
+    public Request buildRequest() {
+        Request.Builder requestBuilder = new Request.Builder();
+        requestBuilder.url(this.constructUrl());
+        this.addHeaders(requestBuilder);
+        
requestBuilder.method(this.method.toString(),this.constructRequestBody());
+        return requestBuilder.build();
+    }
+
+    @NotNull
+    protected HttpUrl constructUrl() {
+        String url = this.baseUrl;
+        if( this.query != null ) {
+            url += this.query.build(false);
+        }
+        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
+        if( this.pathSegments != null ) {
+            for( String path : this.pathSegments ) {
+                urlBuilder.addPathSegments(path);
+            }
+        }
+        if( this.parameters != null ) {
+            for (Map.Entry<String, Object> param : this.parameters.entrySet()) 
{
+                
urlBuilder.addQueryParameter(param.getKey(),param.getValue().toString());
+            }
+        }
+        return urlBuilder.build();
+    }
+
+    protected void addHeaders(@NotNull final Request.Builder requestBuilder) {
+        requestBuilder.addHeader("User-Agent", 
UsergridRequestManager.USERGRID_USER_AGENT);
+        if (this.auth != null ) {
+            String accessToken = this.auth.getAccessToken();
+            if( accessToken != null ) {
+                requestBuilder.addHeader("Authorization", "Bearer " + 
accessToken);
+            }
+        }
+        if( this.headers != null ) {
+            for( Map.Entry<String,Object> header : this.headers.entrySet() ) {
+                
requestBuilder.addHeader(header.getKey(),header.getValue().toString());
+            }
+        }
+    }
+
+    @Nullable
+    protected RequestBody constructRequestBody() {
+        RequestBody requestBody = null;
+        if (method == UsergridHttpMethod.POST || method == 
UsergridHttpMethod.PUT) {
+            String jsonString = "";
+            if( this.data != null ) {
+                jsonString = JsonUtils.toJsonString(this.data);
+            }
+            requestBody = RequestBody.create(this.contentType,jsonString);
+        }
+        return requestBody;
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/UsergridRequestManager.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/UsergridRequestManager.java 
b/src/main/java/org/apache/usergrid/java/client/UsergridRequestManager.java
new file mode 100644
index 0000000..7099d42
--- /dev/null
+++ b/src/main/java/org/apache/usergrid/java/client/UsergridRequestManager.java
@@ -0,0 +1,97 @@
+/*
+ * 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.apache.usergrid.java.client;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.apache.usergrid.java.client.UsergridEnums.UsergridHttpMethod;
+import org.apache.usergrid.java.client.auth.UsergridAppAuth;
+import org.apache.usergrid.java.client.auth.UsergridAuth;
+import org.apache.usergrid.java.client.model.UsergridUser;
+import org.apache.usergrid.java.client.auth.UsergridUserAuth;
+import org.apache.usergrid.java.client.response.UsergridResponse;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.util.Map;
+
+import static org.apache.usergrid.java.client.utils.ObjectUtils.isEmpty;
+
+public class UsergridRequestManager {
+
+    @NotNull public static String USERGRID_USER_AGENT = "usergrid-java/v" + 
Usergrid.UsergridSDKVersion;
+
+    @NotNull private final UsergridClient usergridClient;
+    @NotNull private final OkHttpClient httpClient;
+
+    public UsergridRequestManager(@NotNull final UsergridClient 
usergridClient) {
+        this.usergridClient = usergridClient;
+        this.httpClient = new OkHttpClient();
+    }
+
+    @NotNull
+    public UsergridResponse performRequest(@NotNull final UsergridRequest 
usergridRequest) {
+        Request request = usergridRequest.buildRequest();
+        UsergridResponse usergridResponse;
+        try {
+            Response response = this.httpClient.newCall(request).execute();
+            usergridResponse = 
UsergridResponse.fromResponse(this.usergridClient,usergridRequest,response);
+        } catch( IOException exception ) {
+            usergridResponse = 
UsergridResponse.fromException(this.usergridClient,exception);
+        }
+        return usergridResponse;
+    }
+
+    @NotNull
+    private UsergridResponse authenticate(@NotNull final UsergridAuth auth) {
+        Map<String, String> credentials = auth.credentialsMap();
+        String url = this.usergridClient.clientAppUrl();
+        if ( auth instanceof UsergridUserAuth){
+
+            UsergridUserAuth userAuth = (UsergridUserAuth) auth;
+            if( userAuth.isAdminUser()){
+
+                url = this.usergridClient.managementUrl();
+            }
+
+        }
+
+        UsergridRequest request = new UsergridRequest(UsergridHttpMethod.POST, 
UsergridRequest.APPLICATION_JSON_MEDIA_TYPE, url, null, credentials, 
this.usergridClient.authForRequests(), "token");
+        UsergridResponse response = performRequest(request);
+        if (!isEmpty(response.getAccessToken()) && 
!isEmpty(response.getExpires())) {
+            auth.setAccessToken(response.getAccessToken());
+            auth.setExpiry(System.currentTimeMillis() + response.getExpires() 
- 5000);
+        }
+        return response;
+    }
+
+    @NotNull
+    public UsergridResponse authenticateApp(@NotNull final UsergridAppAuth 
appAuth) {
+        return this.authenticate(appAuth);
+    }
+
+    @NotNull
+    public UsergridResponse authenticateUser(@NotNull final UsergridUserAuth 
userAuth) {
+        UsergridResponse response = this.authenticate(userAuth);
+        UsergridUser responseUser = response.user();
+        if ( response.ok() && responseUser != null) {
+            responseUser.setUserAuth(userAuth);
+        }
+        return response;
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/auth/UsergridAppAuth.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/auth/UsergridAppAuth.java 
b/src/main/java/org/apache/usergrid/java/client/auth/UsergridAppAuth.java
new file mode 100644
index 0000000..a7ac64d
--- /dev/null
+++ b/src/main/java/org/apache/usergrid/java/client/auth/UsergridAppAuth.java
@@ -0,0 +1,55 @@
+/*
+ * 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.apache.usergrid.java.client.auth;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+
+@SuppressWarnings("unused")
+public class UsergridAppAuth extends UsergridAuth {
+
+    @NotNull private String clientId;
+    @NotNull private String clientSecret;
+
+    @NotNull public String getClientId() { return clientId; }
+    public void setClientId(@NotNull final String clientId) { this.clientId = 
clientId; }
+
+    @NotNull private String getClientSecret() { return clientSecret; }
+    public void setClientSecret(@NotNull final String clientSecret) { 
this.clientSecret = clientSecret; }
+
+    @NotNull
+    @Override
+    public HashMap<String, String> credentialsMap() {
+        HashMap<String,String> credentials = super.credentialsMap();
+        credentials.put("grant_type", "client_credentials");
+        credentials.put("client_id", this.clientId);
+        credentials.put("client_secret", this.clientSecret);
+        return credentials;
+    }
+
+    public UsergridAppAuth() {
+        this("","");
+    }
+
+    public UsergridAppAuth(@JsonProperty("clientId") @NotNull final String 
clientId, @JsonProperty("clientSecret") @NotNull final String clientSecret) {
+        super();
+        this.clientId = clientId;
+        this.clientSecret = clientSecret;
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/auth/UsergridAuth.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/auth/UsergridAuth.java 
b/src/main/java/org/apache/usergrid/java/client/auth/UsergridAuth.java
new file mode 100644
index 0000000..1ed61da
--- /dev/null
+++ b/src/main/java/org/apache/usergrid/java/client/auth/UsergridAuth.java
@@ -0,0 +1,76 @@
+/*
+ * 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.apache.usergrid.java.client.auth;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+
+@SuppressWarnings("unused")
+public class UsergridAuth {
+
+    @Nullable private String accessToken = null;
+    @Nullable private Long expiry = null;
+    private boolean usingToken = false;
+    private boolean isAdminUser = false;
+
+    public UsergridAuth() { }
+
+    public UsergridAuth(@JsonProperty("accessToken") @Nullable final String 
accessToken) {
+        this.usingToken = true;
+        setAccessToken(accessToken);
+    }
+
+    public UsergridAuth(@JsonProperty("accessToken") @Nullable final String 
accessToken, @JsonProperty("expiry") @Nullable final Long expiry) {
+        this.usingToken = true;
+        setAccessToken(accessToken);
+        setExpiry(expiry);
+    }
+
+    public void destroy() {
+        setAccessToken(null);
+        setExpiry(null);
+    }
+
+    @Nullable public String getAccessToken() { return accessToken; }
+    public void setAccessToken(@Nullable final String accessToken) {
+        this.accessToken = accessToken;
+    }
+
+    @Nullable public Long getExpiry() { return expiry; }
+    public void setExpiry(@Nullable final Long tokenExpiry) { this.expiry = 
tokenExpiry; }
+
+    public boolean isValidToken() { return (hasToken() && !isExpired()); }
+
+    public boolean hasToken() { return accessToken != null; }
+
+    public boolean isExpired() {
+        if (expiry != null) {
+            Long currentTime = System.currentTimeMillis() / 1000;
+            return ((expiry / 1000) < currentTime);
+        } else {
+            return !this.usingToken;
+        }
+    }
+
+    @NotNull
+    public HashMap<String,String> credentialsMap() {
+        return new HashMap<>();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/auth/UsergridUserAuth.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/auth/UsergridUserAuth.java 
b/src/main/java/org/apache/usergrid/java/client/auth/UsergridUserAuth.java
new file mode 100644
index 0000000..7cb42ad
--- /dev/null
+++ b/src/main/java/org/apache/usergrid/java/client/auth/UsergridUserAuth.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.apache.usergrid.java.client.auth;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+
+@SuppressWarnings("unused")
+public class UsergridUserAuth extends UsergridAuth {
+
+    @NotNull private String username;
+    @NotNull private String password;
+    private boolean isAdminUser = false;
+
+    @NotNull public String getUsername() { return username; }
+    public void setUsername(@NotNull final String username) { this.username = 
username; }
+
+    @NotNull private String getPassword() { return password; }
+    public void setPassword(@NotNull final String password) { this.password = 
password; }
+
+    public boolean isAdminUser() { return isAdminUser; }
+
+    @NotNull
+    @Override
+    public HashMap<String, String> credentialsMap() {
+        HashMap<String,String> credentials = super.credentialsMap();
+        credentials.put("grant_type", "password");
+        credentials.put("username", this.username);
+        credentials.put("password", this.password);
+        return credentials;
+    }
+
+    public UsergridUserAuth() {
+        this("","");
+    }
+
+    public UsergridUserAuth(@JsonProperty("username") @NotNull final String 
username,
+                            @JsonProperty("password") @NotNull final String 
password) {
+        super();
+        this.username = username;
+        this.password = password;
+    }
+
+    public UsergridUserAuth(@JsonProperty("username") @NotNull final String 
username,
+                            @JsonProperty("password") @NotNull final String 
password,
+                            @JsonProperty("isAdminUser") final boolean 
isAdminUser) {
+        super();
+        this.username = username;
+        this.password = password;
+        this.isAdminUser = isAdminUser;
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/exception/UsergridException.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/exception/UsergridException.java
 
b/src/main/java/org/apache/usergrid/java/client/exception/UsergridException.java
new file mode 100644
index 0000000..ff30a0d
--- /dev/null
+++ 
b/src/main/java/org/apache/usergrid/java/client/exception/UsergridException.java
@@ -0,0 +1,50 @@
+/*
+ * 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.apache.usergrid.java.client.exception;
+
+import org.jetbrains.annotations.NotNull;
+
+@SuppressWarnings("unused")
+public class UsergridException extends RuntimeException {
+
+    private int responseCode;
+
+    public int getResponseCode() {
+        return responseCode;
+    }
+    public void setResponseCode(final int responseCode) { this.responseCode = 
responseCode; }
+
+    private UsergridException() {}
+
+    public UsergridException(@NotNull final String message) {
+        super(message);
+    }
+
+    public UsergridException(@NotNull final String message, @NotNull final 
Throwable cause) {
+        super(message, cause);
+    }
+
+    public UsergridException(@NotNull final String message, final int 
responseCode) {
+        super(message);
+        this.responseCode = responseCode;
+    }
+
+    public UsergridException(@NotNull final String message, @NotNull final 
Throwable cause, final int responseCode) {
+        super(message, cause);
+        this.responseCode = responseCode;
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/model/UsergridDevice.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/model/UsergridDevice.java 
b/src/main/java/org/apache/usergrid/java/client/model/UsergridDevice.java
new file mode 100644
index 0000000..1833afb
--- /dev/null
+++ b/src/main/java/org/apache/usergrid/java/client/model/UsergridDevice.java
@@ -0,0 +1,60 @@
+package org.apache.usergrid.java.client.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+@SuppressWarnings("unused")
+public class UsergridDevice extends UsergridEntity {
+    @NotNull public static String DEVICE_ENTITY_TYPE = "device";
+
+    @Nullable private String model;
+    @Nullable private String platform;
+    @Nullable private String osVersion;
+
+    public UsergridDevice() {
+        super(DEVICE_ENTITY_TYPE);
+    }
+
+    public UsergridDevice(@Nullable final String name) {
+        super(DEVICE_ENTITY_TYPE,name);
+    }
+
+    public UsergridDevice(@NotNull final Map<String, JsonNode> properties) {
+        super(DEVICE_ENTITY_TYPE,null,properties);
+    }
+
+    public UsergridDevice(@Nullable final String name, @NotNull final 
Map<String, JsonNode> properties) {
+        super(DEVICE_ENTITY_TYPE,name,properties);
+    }
+
+    @Nullable @JsonProperty("deviceModel")
+    public String getModel() {
+        return this.model;
+    }
+    @JsonProperty("deviceModel")
+    public void setModel(@Nullable final String model) {
+        this.model = model;
+    }
+
+    @Nullable @JsonProperty("devicePlatform")
+    public String getPlatform() {
+        return this.platform;
+    }
+    @JsonProperty("devicePlatform")
+    public void setPlatform(@Nullable final String platform) {
+        this.platform = platform;
+    }
+
+    @Nullable @JsonProperty("deviceOSVersion")
+    public String getOsVersion() {
+        return this.osVersion;
+    }
+    @JsonProperty("deviceOSVersion")
+    public void setOsVersion(@Nullable final String osVersion) {
+        this.osVersion = osVersion;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/model/UsergridEntity.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/model/UsergridEntity.java 
b/src/main/java/org/apache/usergrid/java/client/model/UsergridEntity.java
new file mode 100644
index 0000000..3444de0
--- /dev/null
+++ b/src/main/java/org/apache/usergrid/java/client/model/UsergridEntity.java
@@ -0,0 +1,487 @@
+/*
+ * 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.apache.usergrid.java.client.model;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.node.*;
+import org.apache.usergrid.java.client.UsergridEnums.*;
+import org.apache.usergrid.java.client.Usergrid;
+import org.apache.usergrid.java.client.UsergridClient;
+import org.apache.usergrid.java.client.response.UsergridResponse;
+import org.apache.usergrid.java.client.utils.JsonUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.*;
+
+import static org.apache.usergrid.java.client.utils.JsonUtils.*;
+
+@SuppressWarnings("unused")
+public class UsergridEntity {
+
+    @NotNull private static final HashMap<String,Class<? extends 
UsergridEntity>> subclassMappings = new HashMap<>();
+    @NotNull private static final ObjectMapper entityUpdateMapper = new 
ObjectMapper();
+    @NotNull private final ObjectReader entityUpdateReader = 
entityUpdateMapper.readerForUpdating(this);
+
+    static {
+        subclassMappings.put("user",UsergridUser.class);
+        subclassMappings.put("device",UsergridDevice.class);
+    }
+
+    @NotNull private String type;
+    @Nullable private String uuid;
+    @Nullable private String name;
+    @Nullable private Long created;
+    @Nullable private Long modified;
+
+    @NotNull private Map<String, JsonNode> properties = new HashMap<>();
+
+    public UsergridEntity(@JsonProperty("type") @NotNull final String type) {
+        this.type = type;
+    }
+
+    public UsergridEntity(@NotNull final String type, @Nullable final String 
name) {
+        this(type);
+        if( name != null ) {
+            this.name = name;
+        }
+    }
+
+    public UsergridEntity(@NotNull final String type, @Nullable final String 
name, @NotNull final Map<String, ?> properties) {
+        this(type,name);
+        this.updatePropertiesWithMap(properties);
+    }
+
+    @Nullable
+    public static Class<? extends UsergridEntity> 
customSubclassForType(@NotNull final String type) {
+        return UsergridEntity.subclassMappings.get(type);
+    }
+
+    public void copyAllProperties(@NotNull final UsergridEntity fromEntity) {
+        try {
+            
this.updatePropertiesWithJsonNode(entityUpdateMapper.valueToTree(fromEntity));
+        } catch( IllegalArgumentException e ) { System.out.print("Usergrid 
Error: Unable to update properties from entity - " + fromEntity.toString()); }
+    }
+
+    public void updatePropertiesWithMap(@NotNull final Map<String,?> 
properties) {
+        try {
+            
this.updatePropertiesWithJsonNode(entityUpdateMapper.valueToTree(properties));
+        } catch( IllegalArgumentException e ) { System.out.print("Usergrid 
Error: Unable to update properties from map - " + properties.toString()); }
+    }
+
+    public void updatePropertiesWithJsonNode(@NotNull final JsonNode node) {
+        try {
+            entityUpdateReader.readValue(node);
+        } catch( IOException e ) { System.out.print("Usergrid Error: Unable to 
update properties from jsonNode - " + node.toString()); }
+    }
+
+    public static void mapCustomSubclassToType(@NotNull final String type, 
@NotNull final Class<? extends UsergridEntity> subclass) {
+        UsergridEntity.subclassMappings.put(type,subclass);
+    }
+
+    @NotNull @Override public String toString() {
+        return toJsonString(this);
+    }
+    @NotNull public String toPrettyString() { return toPrettyJsonString(this); 
}
+    @NotNull public JsonNode toJsonObjectValue() {
+        return toJsonNode(this);
+    }
+    @SuppressWarnings("unchecked")
+    @NotNull public Map<String,?> toMapValue() { return toMap(this); }
+
+    @JsonIgnore
+    public boolean isUser() { return (this instanceof UsergridUser || 
this.getType().equalsIgnoreCase(UsergridUser.USER_ENTITY_TYPE)); }
+
+    @NotNull public String getType() { return this.type; }
+    private void setType(@NotNull final String type) { this.type = type; }
+
+    @Nullable public String getUuid() { return this.uuid; }
+    private void setUuid(@NotNull final String uuid) { this.uuid = uuid; }
+
+    @Nullable public String getName() { return this.name; }
+    protected void setName(@Nullable final String name) { this.name = name; }
+
+    @Nullable public Long getCreated() { return this.created; }
+    private void setCreated(@NotNull final Long created) { this.created = 
created; }
+
+    @Nullable public Long getModified() { return this.modified; }
+    private void setModified(@NotNull final Long modified) { this.modified = 
modified; }
+
+    public void setLocation(final double latitude, final double longitude) {
+        ObjectNode rootNode = JsonUtils.createObjectNode();
+        rootNode.put("latitude", latitude);
+        rootNode.put("longitude", longitude);
+        setObjectProperty(this.properties, "location", rootNode);
+    }
+
+    @Nullable
+    public String uuidOrName() {
+        String uuidOrName = this.getUuid();
+        if( uuidOrName == null ) {
+            uuidOrName = this.getName();
+        }
+        return uuidOrName;
+    }
+
+    @NotNull
+    public UsergridResponse reload() {
+        return this.reload(Usergrid.getInstance());
+    }
+
+    @NotNull
+    public UsergridResponse reload(@NotNull final UsergridClient client) {
+        String uuidOrName = this.uuidOrName();
+        if( uuidOrName == null ) {
+            return UsergridResponse.fromError(client,  "No UUID or name 
found.", "The entity object must have a `uuid` or `name` assigned.");
+        }
+        UsergridResponse response = client.GET(this.getType(), uuidOrName);
+        if( response.ok() ) {
+            UsergridEntity responseEntity = response.first();
+            if( responseEntity != null ) {
+                this.copyAllProperties(responseEntity);
+            }
+        }
+        return response;
+    }
+
+    @NotNull
+    public UsergridResponse save() {
+        return this.save(Usergrid.getInstance());
+    }
+
+    @NotNull
+    public UsergridResponse save(@NotNull final UsergridClient client) {
+        UsergridResponse response;
+        if( this.getUuid() != null ) {
+            response = client.PUT(this);
+        } else {
+            response = client.POST(this);
+        }
+        if( response.ok() ) {
+            UsergridEntity responseEntity = response.first();
+            if( responseEntity != null ) {
+                this.copyAllProperties(responseEntity);
+            }
+        }
+        return response;
+    }
+
+    @NotNull
+    public UsergridResponse remove() {
+        return this.remove(Usergrid.getInstance());
+    }
+
+    @NotNull
+    public UsergridResponse remove(@NotNull final UsergridClient client) {
+        return client.DELETE(this);
+    }
+
+    @NotNull
+    public UsergridResponse connect(@NotNull final String relationship, 
@NotNull final UsergridEntity toEntity) {
+        return this.connect(Usergrid.getInstance(), relationship, toEntity);
+    }
+
+    @NotNull
+    public UsergridResponse connect(@NotNull final UsergridClient client, 
@NotNull final String relationship, @NotNull final UsergridEntity toEntity) {
+        return client.connect(this,relationship,toEntity);
+    }
+
+    @NotNull
+    public UsergridResponse disconnect(@NotNull final String relationship, 
@NotNull final UsergridEntity fromEntity) {
+        return this.disconnect(Usergrid.getInstance(), relationship, 
fromEntity);
+    }
+
+    @NotNull
+    public UsergridResponse disconnect(@NotNull final UsergridClient client, 
@NotNull final String relationship, @NotNull final UsergridEntity fromEntity) {
+        return client.disconnect(this,relationship,fromEntity);
+    }
+
+    @NotNull
+    public UsergridResponse getConnections(@NotNull final UsergridDirection 
direction, @NotNull final String relationship) {
+        return 
this.getConnections(Usergrid.getInstance(),direction,relationship);
+    }
+
+    @NotNull
+    public UsergridResponse getConnections(@NotNull final UsergridClient 
client, @NotNull final UsergridDirection direction, @NotNull final String 
relationship) {
+        return client.getConnections(direction,this,relationship);
+    }
+
+    public void removeProperty(@NotNull final String name) {
+        putProperty(name, NullNode.getInstance());
+    }
+
+    public void removeProperties(@NotNull final List<String> names) {
+        for( String propertyName : names ) {
+            this.removeProperty(propertyName);
+        }
+    }
+
+    public void putProperty(@NotNull final String name, @NotNull final String 
value) {
+        this.putProperty(name, JsonNodeFactory.instance.textNode(value));
+    }
+    public void putProperty(@NotNull final String name, final boolean value) {
+        this.putProperty(name, JsonNodeFactory.instance.booleanNode(value));
+    }
+    public void putProperty(@NotNull final String name, @NotNull final List 
value) {
+        this.putProperty(name, JsonNodeFactory.instance.pojoNode(value));
+    }
+    public void putProperty(@NotNull final String name, final int value) {
+        this.putProperty(name, JsonNodeFactory.instance.numberNode(value));
+    }
+    public void putProperty(@NotNull final String name, final long value) {
+        this.putProperty(name, JsonNodeFactory.instance.numberNode(value));
+    }
+    public void putProperty(@NotNull final String name, final float value) {
+        this.putProperty(name, JsonNodeFactory.instance.numberNode(value));
+    }
+    public void putProperty(@NotNull final String name, @Nullable final 
JsonNode value) {
+        UsergridEntityProperties entityProperty = 
UsergridEntityProperties.fromString(name);
+        if( entityProperty != null && 
!entityProperty.isMutableForEntity(this)) {
+            return;
+        }
+
+        JsonNode valueNode = value;
+        if( valueNode == null ) {
+            valueNode = NullNode.getInstance();
+        }
+        this.updatePropertiesWithMap(Collections.singletonMap(name,valueNode));
+    }
+    public void putProperties(@NotNull final String jsonString) {
+        try {
+            JsonNode jsonNode = entityUpdateMapper.readTree(jsonString);
+            this.putProperties(jsonNode);
+        } catch( Exception ignore ) {}
+    }
+    public void putProperties(@NotNull final Map<String, Object> properties) {
+        try {
+            JsonNode jsonNode = entityUpdateMapper.valueToTree(properties);
+            this.putProperties(jsonNode);
+        } catch( Exception ignore ) {}
+    }
+    public void putProperties(@NotNull final JsonNode jsonNode) {
+        HashMap<String,JsonNode> propertiesToUpdate = new HashMap<>();
+        Iterator<Map.Entry<String,JsonNode>> keys = jsonNode.fields();
+        while (keys.hasNext()) {
+            Map.Entry<String,JsonNode> entry = keys.next();
+            String key = entry.getKey();
+            UsergridEntityProperties entityProperty = 
UsergridEntityProperties.fromString(key);
+            if( entityProperty == null || 
entityProperty.isMutableForEntity(this) ) {
+                propertiesToUpdate.put(key,entry.getValue());
+            }
+        }
+        if( !propertiesToUpdate.isEmpty() ) {
+            this.updatePropertiesWithMap(propertiesToUpdate);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public void append(@NotNull final String name, @NotNull final Object 
value) {
+        this.append(name, (value instanceof List) ? (List<Object>) value : 
Collections.singletonList(value));
+    }
+
+    public void append(@NotNull final String name, @NotNull final List<Object> 
value) {
+        this.insert(name, value, Integer.MAX_VALUE);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void insert(@NotNull final String name, @NotNull final Object 
value) {
+        this.insert(name, (value instanceof List) ? (List<Object>) value : 
Collections.singletonList(value), 0);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void insert(@NotNull final String name, @NotNull final Object 
value, final int index) {
+        this.insert(name, (value instanceof List) ? (List<Object>) value : 
Collections.singletonList(value), index);
+    }
+
+    public void insert(@NotNull final String name, @NotNull final List<Object> 
value) {
+        this.insert(name,value,0);
+    }
+
+    public void insert(@NotNull final String name, @NotNull final List<Object> 
value, final int index) {
+        int indexToInsert = index;
+        if (indexToInsert < 0) {
+            indexToInsert = 0;
+        }
+        Object propertyValue = this.getEntityProperty(name);
+        if( propertyValue != null ) {
+            ArrayList<Object> propertyArrayValue = 
this.convertToList(propertyValue);
+            propertyArrayValue = 
this.insertIntoArray(propertyArrayValue,value,indexToInsert);
+            this.putProperty(name, propertyArrayValue);
+        } else {
+            this.putProperty(name, value);
+        }
+    }
+
+    public void pop(@NotNull final String name) {
+        ArrayList<Object> arrayToPop = this.getArrayToPopOrShift(name);
+        if( arrayToPop != null && !arrayToPop.isEmpty() ) {
+            arrayToPop.remove(arrayToPop.size() - 1);
+            this.putProperty(name, arrayToPop);
+        }
+    }
+
+    public void shift(@NotNull final String name) {
+        ArrayList<Object> arrayToShift = this.getArrayToPopOrShift(name);
+        if( arrayToShift != null && !arrayToShift.isEmpty() ) {
+            arrayToShift.remove(0);
+            this.putProperty(name, arrayToShift);
+        }
+    }
+
+    @Nullable
+    public <T> T getEntityProperty(@NotNull final String name) {
+        return JsonUtils.getProperty(this.properties, name);
+    }
+
+    @Nullable
+    public JsonNode getJsonNodeProperty(@NotNull final String name) {
+        return this.getProperties().get(name);
+    }
+
+    @Nullable
+    public String getStringProperty(@NotNull final String name) {
+        return JsonUtils.getStringProperty(this.getProperties(), name);
+    }
+
+    @Nullable
+    public Boolean getBooleanProperty(@NotNull final String name) {
+        Boolean booleanValue = null;
+        Object object = JsonUtils.getProperty(this.getProperties(), name);
+        if( object instanceof Boolean ) {
+            booleanValue = (Boolean)object;
+        }
+        return booleanValue;
+    }
+
+    @Nullable
+    public Number getNumberProperty(@NotNull final String name) {
+        Number numberValue = null;
+        Object object = JsonUtils.getProperty(this.getProperties(), name);
+        if( object instanceof Number ) {
+            numberValue = (Number)object;
+        }
+        return numberValue;
+    }
+
+    @Nullable
+    public Integer getIntegerProperty(@NotNull final String name) {
+        Integer integerValue = null;
+        Object object = JsonUtils.getProperty(this.getProperties(), name);
+        if( object instanceof Number ) {
+            integerValue = ((Number)object).intValue();
+        }
+        return integerValue;
+    }
+
+    @Nullable
+    public Float getFloatProperty(@NotNull final String name) {
+        Float floatValue = null;
+        Object object = JsonUtils.getProperty(this.getProperties(), name);
+        if( object instanceof Number ) {
+            floatValue = ((Number)object).floatValue();
+        }
+        return floatValue;
+    }
+
+    @Nullable
+    public Long getLongProperty(@NotNull final String name) {
+        Long longValue = null;
+        Object object = JsonUtils.getProperty(this.getProperties(), name);
+        if( object instanceof Number ) {
+            longValue = ((Number)object).longValue();
+        }
+        return longValue;
+    }
+
+    @JsonAnyGetter @NotNull
+    public Map<String, JsonNode> getProperties() {
+        return this.properties;
+    }
+
+    @JsonAnySetter
+    private void internalPutProperty(@NotNull final String name, @Nullable 
final JsonNode value) {
+        if (value == null) {
+            properties.put(name, NullNode.instance);
+        } else {
+            properties.put(name, value);
+        }
+    }
+
+    @Nullable
+    @SuppressWarnings("unchecked")
+    private ArrayList<Object> getArrayToPopOrShift(@NotNull final String name) 
{
+        Object entityProperty = getEntityProperty(name);
+        ArrayList<Object> arrayToPopOrShift = null;
+        if (entityProperty instanceof POJONode) {
+            Object objectValue = ((POJONode) entityProperty).getPojo();
+            if (objectValue instanceof List) {
+                arrayToPopOrShift = new ArrayList<>((List) objectValue);
+            } else {
+                arrayToPopOrShift = new ArrayList<>();
+                arrayToPopOrShift.add(objectValue);
+            }
+        } else if( entityProperty instanceof ArrayNode ) {
+            arrayToPopOrShift = 
JsonUtils.convertToArrayList((ArrayNode)entityProperty);
+        } else if( entityProperty instanceof List ) {
+            arrayToPopOrShift = new ArrayList<>((List) entityProperty);
+        }
+        return arrayToPopOrShift;
+    }
+
+    @NotNull
+    private ArrayList<Object> convertToList(@NotNull final Object value) {
+        ArrayList<Object> arrayList = new ArrayList<>();
+        if( value instanceof ArrayNode ) {
+            arrayList = JsonUtils.convertToArrayList((ArrayNode)value);
+        } else if (value instanceof POJONode) {
+            Object objectValue = ((POJONode) value).getPojo();
+            if( objectValue instanceof List ) {
+                arrayList.addAll((List)objectValue);
+            } else {
+                arrayList.add(objectValue);
+            }
+        } else if (value instanceof List) {
+            arrayList.addAll((List)value);
+        } else {
+            arrayList.add(value);
+        }
+        return arrayList;
+    }
+
+    @NotNull
+    private ArrayList<Object> insertIntoArray(@NotNull final List<Object> 
propertyArrayNode, @NotNull final List<Object> arrayToInsert, final int index) {
+        ArrayList<Object> mergedArray = new ArrayList<>();
+        if (propertyArrayNode.size() <= 0 || arrayToInsert.isEmpty()) {
+            mergedArray.addAll(arrayToInsert);
+        }  else if ( index <= 0 ) {
+            mergedArray.addAll(arrayToInsert);
+            mergedArray.addAll(propertyArrayNode);
+        } else if ( index > 0 ) {
+            mergedArray.addAll(propertyArrayNode);
+            if ( index > propertyArrayNode.size() ) {
+                mergedArray.addAll(arrayToInsert);
+            } else {
+                mergedArray.addAll(index,arrayToInsert);
+            }
+        }
+        return mergedArray;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/model/UsergridUser.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/model/UsergridUser.java 
b/src/main/java/org/apache/usergrid/java/client/model/UsergridUser.java
new file mode 100644
index 0000000..f967e46
--- /dev/null
+++ b/src/main/java/org/apache/usergrid/java/client/model/UsergridUser.java
@@ -0,0 +1,198 @@
+/*
+ * 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.apache.usergrid.java.client.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.usergrid.java.client.Usergrid;
+import org.apache.usergrid.java.client.UsergridClient;
+import org.apache.usergrid.java.client.UsergridEnums.*;
+import org.apache.usergrid.java.client.auth.UsergridUserAuth;
+import org.apache.usergrid.java.client.query.UsergridQuery;
+import org.apache.usergrid.java.client.response.UsergridResponse;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+
+@SuppressWarnings("unused")
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class UsergridUser extends UsergridEntity {
+    @NotNull public final static String USER_ENTITY_TYPE = "user";
+
+    @Nullable private UsergridUserAuth userAuth = null;
+
+    @Nullable private String username;
+    @Nullable private String email;
+    @Nullable private String password;
+    @Nullable private String picture;
+
+    private boolean activated = false;
+    private boolean disabled = false;
+
+    public UsergridUser() {
+        super(USER_ENTITY_TYPE);
+    }
+
+    public UsergridUser(@NotNull final String username, @Nullable final String 
password) {
+        super(USER_ENTITY_TYPE);
+        setUsername(username);
+        setPassword(password);
+    }
+
+    public UsergridUser(@NotNull final String name, @NotNull final 
HashMap<String, Object> propertyMap) {
+        super(USER_ENTITY_TYPE,name);
+        putProperties(propertyMap);
+    }
+
+    public UsergridUser(@Nullable final String name, @Nullable final String 
username, @Nullable final String email, @Nullable final String password) {
+        super(USER_ENTITY_TYPE,name);
+        setUsername(username);
+        setEmail(email);
+        setPassword(password);
+    }
+
+    public void setName(@Nullable final String name) { super.setName(name); }
+
+    @Nullable public String getUsername() { return this.username; }
+    public void setUsername(@Nullable final String username) { this.username = 
username; }
+
+    @Nullable public String getEmail() { return this.email; }
+    public void setEmail(@Nullable final String email) { this.email = email; }
+
+    @Nullable public String getPassword() { return this.password; }
+    public void setPassword(@Nullable final String password) { this.password = 
password; }
+
+    @Nullable public String getPicture() { return this.picture; }
+    public void setPicture(@Nullable final String picture) { this.picture = 
picture; }
+
+    public boolean isActivated() { return this.activated; }
+    public void setActivated(final boolean activated) { this.activated = 
activated; }
+
+    public boolean isDisabled() { return this.disabled; }
+    public void setDisabled(final boolean disabled) { this.disabled = 
disabled; }
+
+    @JsonIgnore @Nullable public UsergridUserAuth getUserAuth() { return 
this.userAuth; }
+    @JsonIgnore public void setUserAuth(@Nullable final UsergridUserAuth 
userAuth) { this.userAuth = userAuth; }
+
+    @Nullable
+    public String uuidOrUsername() {
+        String uuidOrUsername = this.getUuid();
+        if( uuidOrUsername == null ) {
+            uuidOrUsername = this.getUsername();
+        }
+        return uuidOrUsername;
+    }
+
+    @Nullable
+    public String usernameOrEmail() {
+        String usernameOrEmail = this.getUsername();
+        if( usernameOrEmail == null ) {
+            usernameOrEmail = this.getEmail();
+        }
+        return usernameOrEmail;
+    }
+
+    public static boolean checkAvailable(@Nullable final String email, 
@Nullable final String username) {
+        return UsergridUser.checkAvailable(Usergrid.getInstance(), email, 
username);
+    }
+
+    public static boolean checkAvailable(@NotNull final UsergridClient client, 
@Nullable final String email, @Nullable final String username) {
+        if (email == null && username == null) {
+            throw new IllegalArgumentException("email and username both are 
null ");
+        }
+        UsergridQuery query = new UsergridQuery(USER_ENTITY_TYPE);
+        if (username != null) {
+            query.eq(UsergridUserProperties.USERNAME.toString(), username);
+        }
+        if (email != null) {
+            query.or().eq(UsergridUserProperties.EMAIL.toString(), email);
+        }
+        return client.GET(query).first() != null;
+    }
+
+    @NotNull
+    public UsergridResponse create() {
+        return this.create(Usergrid.getInstance());
+    }
+
+    @NotNull
+    public UsergridResponse create(@NotNull final UsergridClient client) {
+        UsergridResponse response = client.POST(this);
+        UsergridUser createdUser = response.user();
+        if( createdUser != null ) {
+            this.copyAllProperties(createdUser);
+        }
+        return response;
+    }
+
+    @NotNull
+    public UsergridResponse login(@NotNull final String username, @NotNull 
final String password) {
+        return this.login(Usergrid.getInstance(),username,password);
+    }
+
+    @NotNull
+    public UsergridResponse login(@NotNull final UsergridClient client, 
@NotNull final String username, @NotNull final String password) {
+        UsergridUserAuth userAuth = new UsergridUserAuth(username,password);
+        UsergridResponse response = client.authenticateUser(userAuth,false);
+        if( response.ok() ) {
+            this.userAuth = userAuth;
+        }
+        return response;
+    }
+
+    @NotNull
+    public UsergridResponse resetPassword(@NotNull final String oldPassword, 
@NotNull final String newPassword) {
+        return 
this.resetPassword(Usergrid.getInstance(),oldPassword,newPassword);
+    }
+
+    @NotNull
+    public UsergridResponse resetPassword(@NotNull final UsergridClient 
client, @NotNull final String oldPassword, @NotNull final String newPassword) {
+        return client.resetPassword(this,oldPassword,newPassword);
+    }
+
+    @NotNull
+    public UsergridResponse reauthenticate() {
+        return this.reauthenticate(Usergrid.getInstance());
+    }
+
+    @NotNull
+    public UsergridResponse reauthenticate(@NotNull final UsergridClient 
client) {
+        return this.userAuth == null ? UsergridResponse.fromError(client, 
"Invalid UsergridUserAuth.", "No UsergridUserAuth found on the UsergridUser.") 
: client.authenticateUser(this.userAuth, false);
+    }
+
+    @NotNull
+    public UsergridResponse logout() {
+        return this.logout(Usergrid.getInstance());
+    }
+
+    @NotNull
+    public UsergridResponse logout(@NotNull final UsergridClient client) {
+        UsergridResponse response;
+        String uuidOrUsername = this.uuidOrUsername();
+        String accessToken = (this.userAuth != null) ? 
this.userAuth.getAccessToken() : null;
+        if (uuidOrUsername == null || accessToken == null ) {
+            response = UsergridResponse.fromError(client,  "Logout Failed.", 
"UUID or Access Token not found on UsergridUser object.");
+        } else {
+            response = client.logoutUser(uuidOrUsername, accessToken);
+            if( response.ok() ) {
+                this.userAuth = null;
+            }
+        }
+        return response;
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/query/UsergridQuery.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/query/UsergridQuery.java 
b/src/main/java/org/apache/usergrid/java/client/query/UsergridQuery.java
new file mode 100644
index 0000000..e8c78c2
--- /dev/null
+++ b/src/main/java/org/apache/usergrid/java/client/query/UsergridQuery.java
@@ -0,0 +1,431 @@
+/*
+ * 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.apache.usergrid.java.client.query;
+
+import org.apache.usergrid.java.client.UsergridEnums.UsergridQueryOperator;
+import org.apache.usergrid.java.client.UsergridEnums.UsergridQuerySortOrder;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.net.URLEncoder;
+import java.util.*;
+
+@SuppressWarnings("unused")
+public final class UsergridQuery {
+
+    @NotNull private final ArrayList<String> requirementStrings = new 
ArrayList<>();
+    @NotNull private final ArrayList<String> urlTerms = new ArrayList<>();
+    @NotNull private final HashMap<String, UsergridQuerySortOrder> 
orderClauses = new HashMap<>();
+    @NotNull private Integer limit = UsergridQuery.LIMIT_DEFAULT;
+    @Nullable private String cursor = null;
+    @Nullable private String fromStringValue = null;
+    @Nullable private String collectionName = null;
+
+    public UsergridQuery() {
+        this(null);
+    }
+
+    public UsergridQuery(@Nullable final String collectionName) {
+        this.collectionName = collectionName;
+        this.requirementStrings.add(UsergridQuery.EMPTY_STRING);
+    }
+
+    private static boolean isUUID(@NotNull final String string) {
+        try {
+            UUID uuid = UUID.fromString(string);
+            return true;
+        } catch (Exception ex) {
+            return false;
+        }
+    }
+
+    @NotNull
+    private static String encode(@NotNull final String stringValue) {
+        String escapedString;
+        try {
+            escapedString = URLEncoder.encode(stringValue, UTF8);
+        } catch (Exception e) {
+            escapedString = stringValue;
+        }
+        return escapedString;
+    }
+
+    @NotNull
+    public static String strJoin(@NotNull final List<String> array, @NotNull 
final String separator) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (int i = 0, il = array.size(); i < il; i++) {
+            if (i > 0) {
+                stringBuilder.append(separator);
+            }
+            stringBuilder.append(array.get(i));
+        }
+        return stringBuilder.toString();
+    }
+
+    @NotNull
+    public UsergridQuery fromString(@NotNull final String stringValue) {
+        this.fromStringValue = stringValue;
+        return this;
+    }
+
+    @Nullable
+    public String getType() {
+        return this.collectionName;
+    }
+
+    @Nullable
+    public String getCollectionName() {
+        return this.collectionName;
+    }
+
+    @Nullable
+    public String getCollection() {
+        return this.collectionName;
+    }
+
+    @NotNull
+    public UsergridQuery type(@Nullable final String type) {
+        this.collectionName = type;
+        return this;
+    }
+
+    @NotNull
+    public UsergridQuery collection(@Nullable final String collectionName) {
+        return this.type(collectionName);
+    }
+
+    @NotNull
+    public UsergridQuery collectionName(@Nullable final String collectionName) 
{
+        return this.type(collectionName);
+    }
+
+    @NotNull
+    public UsergridQuery cursor(@Nullable final String value) {
+        this.cursor = value;
+        return this;
+    }
+
+    @NotNull
+    public UsergridQuery limit(@NotNull final Integer limit) {
+        this.limit = limit;
+        return this;
+    }
+
+    @NotNull
+    private UsergridQuery addConditionalSeparator(@NotNull final String 
separator) {
+        if (!this.requirementStrings.get(0).isEmpty()) {
+            this.requirementStrings.add(0, separator);
+            this.requirementStrings.add(0, UsergridQuery.EMPTY_STRING);
+        }
+        return this;
+    }
+
+    @NotNull
+    public UsergridQuery and() {
+        return this.addConditionalSeparator(UsergridQuery.AND);
+    }
+
+    @NotNull
+    public UsergridQuery or() {
+        return this.addConditionalSeparator(UsergridQuery.OR);
+    }
+
+    @NotNull
+    public UsergridQuery not() {
+        return this.addConditionalSeparator(UsergridQuery.NOT);
+    }
+
+    @NotNull
+    public UsergridQuery sort(@NotNull final String term, @NotNull final 
UsergridQuerySortOrder sortOrder) {
+        this.orderClauses.put(term, sortOrder);
+        return this;
+    }
+
+    @NotNull
+    public UsergridQuery ascending(@NotNull final String term) {
+        return this.asc(term);
+    }
+
+    @NotNull
+    public UsergridQuery asc(@NotNull final String term) {
+        return this.sort(term, UsergridQuerySortOrder.ASC);
+    }
+
+    @NotNull
+    public UsergridQuery descending(@NotNull final String term) {
+        return this.desc(term);
+    }
+
+    @NotNull
+    public UsergridQuery desc(@NotNull final String term) {
+        return this.sort(term, UsergridQuerySortOrder.DESC);
+    }
+
+    @NotNull
+    public UsergridQuery contains(@NotNull final String term, @NotNull final 
String value) {
+        return this.containsWord(term, value);
+    }
+
+    @NotNull
+    public UsergridQuery containsString(@NotNull final String term, @NotNull 
final String value) {
+        return this.containsWord(term, value);
+    }
+
+    @NotNull
+    public UsergridQuery containsWord(@NotNull final String term, @NotNull 
final String value) {
+        return this.addRequirement(term + SPACE + CONTAINS + SPACE + 
((UsergridQuery.isUUID(value)) ? EMPTY_STRING : APOSTROPHE) + value + 
((UsergridQuery.isUUID(value)) ? EMPTY_STRING : APOSTROPHE));
+    }
+
+    @NotNull
+    public UsergridQuery filter(@NotNull final String term, @NotNull final 
Object value) {
+        return this.eq(term, value);
+    }
+
+    @NotNull
+    public UsergridQuery equals(@NotNull final String term, @NotNull final 
Object value) {
+        return this.eq(term, value);
+    }
+
+    @NotNull
+    public UsergridQuery eq(@NotNull final String term, @NotNull final Object 
value) {
+        return this.addOperationRequirement(term, UsergridQueryOperator.EQUAL, 
value);
+    }
+
+    @NotNull
+    public UsergridQuery greaterThan(@NotNull final String term, @NotNull 
final Object value) {
+        return this.gt(term, value);
+    }
+
+    @NotNull
+    public UsergridQuery gt(@NotNull final String term, @NotNull final Object 
value) {
+        return this.addOperationRequirement(term, 
UsergridQueryOperator.GREATER_THAN, value);
+    }
+
+    @NotNull
+    public UsergridQuery greaterThanOrEqual(@NotNull final String term, 
@NotNull final Object value) {
+        return this.gte(term, value);
+    }
+
+    @NotNull
+    public UsergridQuery gte(@NotNull final String term, @NotNull final Object 
value) {
+        return this.addOperationRequirement(term, 
UsergridQueryOperator.GREATER_THAN_EQUAL_TO, value);
+    }
+
+    @NotNull
+    public UsergridQuery lessThan(@NotNull final String term, @NotNull final 
Object value) {
+        return this.lt(term, value);
+    }
+
+    @NotNull
+    public UsergridQuery lt(@NotNull final String term, @NotNull final Object 
value) {
+        return this.addOperationRequirement(term, 
UsergridQueryOperator.LESS_THAN, value);
+    }
+
+    @NotNull
+    public UsergridQuery lessThanOrEqual(@NotNull final String term, @NotNull 
final Object value) {
+        return this.lte(term, value);
+    }
+
+    @NotNull
+    public UsergridQuery lte(@NotNull final String term, @NotNull final Object 
value) {
+        return this.addOperationRequirement(term, 
UsergridQueryOperator.LESS_THAN_EQUAL_TO, value);
+    }
+
+    @NotNull
+    public UsergridQuery locationWithin(final double distance, final double 
latitude, final double longitude) {
+        return this.addRequirement(LOCATION + SPACE + WITHIN + SPACE + 
distance + SPACE + OF + SPACE + latitude + SPACE + COMMA + longitude);
+    }
+
+    @NotNull
+    public UsergridQuery urlTerm(@NotNull final String term, @NotNull final 
String equalsValue) {
+        if (term.equalsIgnoreCase(QL)) {
+            this.ql(equalsValue);
+        } else {
+            this.urlTerms.add(UsergridQuery.encode(term) + EQUALS + 
UsergridQuery.encode(equalsValue));
+        }
+        return this;
+    }
+
+    @NotNull
+    public UsergridQuery ql(final String value) {
+
+        return value != null && !value.isEmpty() ? this.addRequirement(value) 
: this;
+
+    }
+
+    @NotNull
+    public UsergridQuery addRequirement(@NotNull final String requirement) {
+        String requirementString = this.requirementStrings.remove(0);
+        if (!requirement.isEmpty() && !requirementString.isEmpty()) {
+            requirementString += SPACE + AND + SPACE;
+        }
+        requirementString += requirement;
+        this.requirementStrings.add(0, requirementString);
+        return this;
+    }
+
+    @NotNull
+    public UsergridQuery addOperationRequirement(@NotNull final String term, 
@NotNull final UsergridQueryOperator operation, final int intValue) {
+        return this.addOperationRequirement(term, operation, 
Integer.valueOf(intValue));
+    }
+
+    @NotNull
+    public UsergridQuery addOperationRequirement(@NotNull final String term, 
@NotNull final UsergridQueryOperator operation, @NotNull final Object value) {
+        if (value instanceof String) {
+            String valueString = value.toString();
+            if (!UsergridQuery.isUUID(valueString)) {
+                valueString = APOSTROPHE + value + APOSTROPHE;
+            }
+            return addRequirement(term + SPACE + operation.operatorValue() + 
SPACE + valueString);
+        } else {
+            return addRequirement(term + SPACE + operation.operatorValue() + 
SPACE + value.toString());
+        }
+    }
+
+    @NotNull
+    private String constructOrderByString() {
+        String orderByString = EMPTY_STRING;
+        if (!this.orderClauses.isEmpty()) {
+            for (Map.Entry<String, UsergridQuerySortOrder> orderClause : 
this.orderClauses.entrySet()) {
+                if (!orderByString.isEmpty()) {
+                    orderByString += COMMA;
+                }
+                orderByString += orderClause.getKey() + SPACE + 
orderClause.getValue().toString();
+            }
+            if (!orderByString.isEmpty()) {
+                orderByString = SPACE + ORDER_BY + SPACE + orderByString;
+            }
+        }
+        return orderByString;
+    }
+
+    @NotNull
+    private String constructURLTermsString() {
+        String urlTermsString = EMPTY_STRING;
+        if (!this.urlTerms.isEmpty()) {
+            urlTermsString = UsergridQuery.strJoin(this.urlTerms, AMPERSAND);
+        }
+        return urlTermsString;
+    }
+
+    @NotNull
+    private String constructRequirementString() {
+        ArrayList<String> requirementStrings = new 
ArrayList<>(this.requirementStrings);
+        String firstString = requirementStrings.get(0);
+        if (firstString.isEmpty()) {
+            requirementStrings.remove(0);
+        }
+        String requirementsString = EMPTY_STRING;
+        if (!requirementStrings.isEmpty()) {
+            firstString = requirementStrings.get(0);
+            if (firstString.equalsIgnoreCase(OR) || 
firstString.equalsIgnoreCase(AND) || firstString.equalsIgnoreCase(NOT)) {
+                requirementStrings.remove(0);
+            }
+            if (!requirementStrings.isEmpty()) {
+                Collections.reverse(requirementStrings);
+                requirementsString = UsergridQuery.strJoin(requirementStrings, 
SPACE);
+            }
+        }
+        return requirementsString;
+    }
+
+    @NotNull
+    private String constructURLAppend() {
+        return this.constructURLAppend(true);
+    }
+
+    @NotNull
+    private String constructURLAppend(final boolean autoURLEncode) {
+        if (this.fromStringValue != null) {
+            String requirementsString = this.fromStringValue;
+            if (autoURLEncode) {
+                requirementsString = UsergridQuery.encode(requirementsString);
+            }
+            return QUESTION_MARK + QL + EQUALS + requirementsString;
+        }
+        String urlAppend = EMPTY_STRING;
+        if (this.limit != LIMIT_DEFAULT) {
+            urlAppend += LIMIT + EQUALS + this.limit.toString();
+        }
+        String urlTermsString = this.constructURLTermsString();
+        if (!urlTermsString.isEmpty()) {
+            if (!urlAppend.isEmpty()) {
+                urlAppend += AMPERSAND;
+            }
+            urlAppend += urlTermsString;
+        }
+        if (this.cursor != null && !this.cursor.isEmpty()) {
+            if (!urlAppend.isEmpty()) {
+                urlAppend += AMPERSAND;
+            }
+            urlAppend += CURSOR + EQUALS + this.cursor;
+        }
+
+        String requirementsString = this.constructRequirementString();
+
+        String orderByString = this.constructOrderByString();
+        if (!orderByString.isEmpty()) {
+            requirementsString += orderByString;
+        }
+        if (!requirementsString.isEmpty()) {
+            if (autoURLEncode) {
+                requirementsString = UsergridQuery.encode(requirementsString);
+            }
+            if (!urlAppend.isEmpty()) {
+                urlAppend += AMPERSAND;
+            }
+            urlAppend += QL + EQUALS + requirementsString;
+        }
+        if (!urlAppend.isEmpty()) {
+            urlAppend = QUESTION_MARK + urlAppend;
+        }
+        return urlAppend;
+    }
+
+    @NotNull
+    public String build() {
+        return this.build(true);
+    }
+
+    @NotNull
+    public String build(final boolean autoURLEncode) {
+        return this.constructURLAppend(autoURLEncode);
+    }
+
+    private static final int LIMIT_DEFAULT = 10;
+    @NotNull private static final String AMPERSAND = "&";
+    @NotNull private static final String AND = "and";
+    @NotNull private static final String APOSTROPHE = "'";
+    @NotNull private static final String COMMA = ",";
+    @NotNull private static final String CONTAINS = "contains";
+    @NotNull private static final String CURSOR = "cursor";
+    @NotNull private static final String EMPTY_STRING = "";
+    @NotNull private static final String EQUALS = "=";
+    @NotNull private static final String LIMIT = "limit";
+    @NotNull private static final String LOCATION = "location";
+    @NotNull private static final String NOT = "not";
+    @NotNull private static final String OF = "of";
+    @NotNull private static final String OR = "or";
+    @NotNull private static final String ORDER_BY = "order by";
+    @NotNull private static final String QL = "ql";
+    @NotNull private static final String QUESTION_MARK = "?";
+    @NotNull private static final String SELECT_ALL = "select *";
+    @NotNull private static final String SPACE = " ";
+    @NotNull private static final String UTF8 = "UTF-8";
+    @NotNull private static final String WHERE = "where";
+    @NotNull private static final String WITHIN = "within";
+}

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/response/UsergridResponse.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/response/UsergridResponse.java 
b/src/main/java/org/apache/usergrid/java/client/response/UsergridResponse.java
new file mode 100644
index 0000000..ee649c4
--- /dev/null
+++ 
b/src/main/java/org/apache/usergrid/java/client/response/UsergridResponse.java
@@ -0,0 +1,230 @@
+/*
+ * 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.apache.usergrid.java.client.response;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.databind.JsonNode;
+import okhttp3.Headers;
+import org.apache.usergrid.java.client.UsergridClient;
+import org.apache.usergrid.java.client.UsergridEnums;
+import org.apache.usergrid.java.client.UsergridRequest;
+import org.apache.usergrid.java.client.model.UsergridEntity;
+import org.apache.usergrid.java.client.model.UsergridUser;
+import org.apache.usergrid.java.client.query.UsergridQuery;
+import org.apache.usergrid.java.client.utils.JsonUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+import static org.apache.usergrid.java.client.utils.JsonUtils.toJsonString;
+
+@SuppressWarnings("unused")
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class UsergridResponse {
+
+    @Nullable private UsergridClient client;
+    @NotNull private Map<String, JsonNode> properties = new HashMap<>();
+
+    private int statusCode = 0;
+    @Nullable private JsonNode responseJson = null;
+    @Nullable private String cursor;
+    @Nullable private List<UsergridEntity> entities;
+    @Nullable private Map<String, String> headers;
+    @Nullable private UsergridQuery query;
+    @Nullable private UsergridResponseError responseError = null;
+
+    @Nullable private String accessToken;
+    @Nullable private Long expires;
+
+    public boolean ok() { return (statusCode > 0 && statusCode < 400); }
+    public int count()  { return (entities == null) ? 0 : entities.size(); }
+    public boolean hasNextPage() { return (cursor != null); }
+    @NotNull @Override public String toString() {
+        return toJsonString(this);
+    }
+
+    @Nullable public UsergridEntity first() { return (entities == null || 
entities.isEmpty()) ? null : entities.get(0); }
+    @Nullable public UsergridEntity entity() {
+        return first();
+    }
+    @Nullable public UsergridEntity last() { return (entities == null || 
entities.isEmpty()) ? null : entities.get(entities.size() - 1); }
+
+    @Nullable
+    public UsergridUser user() {
+        UsergridEntity entity = this.first();
+        if( entity != null && entity instanceof UsergridUser ) {
+            return (UsergridUser) entity;
+        }
+        return null;
+    }
+
+    @Nullable
+    public List<UsergridUser> users() {
+        ArrayList<UsergridUser> users = null;
+        if( entities != null && !entities.isEmpty() ) {
+            for( UsergridEntity entity : entities ) {
+                if( entity instanceof UsergridUser ) {
+                    if( users == null )  {
+                        users = new ArrayList<>();
+                    }
+                    users.add((UsergridUser)entity);
+                }
+            }
+        }
+        return users;
+    }
+
+    public int getStatusCode() { return this.statusCode; }
+
+    @Nullable @JsonIgnore
+    public UsergridClient getClient() {
+        return client;
+    }
+    @JsonIgnore public void setClient(@Nullable final UsergridClient client) { 
this.client = client; }
+
+    @Nullable @JsonIgnore
+    public JsonNode getResponseJson() {
+        return responseJson;
+    }
+    private void setResponseJson(@Nullable final JsonNode responseJson) 
{this.responseJson = responseJson; }
+
+    @Nullable @JsonIgnore
+    public UsergridQuery getQuery() {
+        return query;
+    }
+    private void setQuery(@Nullable final UsergridQuery query) { this.query = 
query; }
+
+    @Nullable
+    public UsergridResponseError getResponseError() {
+        return responseError;
+    }
+    private void setResponseError(@Nullable final UsergridResponseError 
responseError) { this.responseError = responseError; }
+
+    @Nullable
+    public Map<String, String> getHeaders() {
+        return headers;
+    }
+    private void setHeaders(@Nullable final Map<String, String> headers) { 
this.headers = headers; }
+
+    @Nullable
+    public List<UsergridEntity> getEntities() { return entities; }
+    private void setEntities(@NotNull final List<UsergridEntity> entities) { 
this.entities = entities; }
+
+    @Nullable @JsonProperty("cursor")
+    public String getCursor() {
+        return cursor;
+    }
+    @JsonProperty("cursor")
+    private void setCursor(@NotNull final String cursor) { this.cursor = 
cursor; }
+
+    @Nullable @JsonProperty("access_token")
+    public String getAccessToken() { return this.accessToken; }
+    @JsonProperty("access_token")
+    private void setAccessToken(@NotNull final String accessToken) { 
this.accessToken = accessToken; }
+
+    @Nullable @JsonProperty("expires_in")
+    public Long getExpires() { return this.expires; }
+    @JsonProperty("expires_in")
+    private void setExpires(@NotNull final Long expires) { this.expires = 
expires; }
+
+    @JsonProperty("user")
+    private void setUser(@NotNull final UsergridUser user) {
+        if( this.entities == null ) {
+            this.entities = new ArrayList<>();
+        }
+        this.entities.add(user);
+    }
+
+    @NotNull @JsonAnyGetter
+    public Map<String, JsonNode> getProperties() {
+        return properties;
+    }
+    @JsonAnySetter
+    private void setProperty(@NotNull final  String key, @NotNull final 
JsonNode value) {
+        properties.put(key, value);
+    }
+
+    @NotNull
+    public UsergridResponse loadNextPage() {
+        UsergridClient client = this.client;
+        UsergridEntity entity = this.first();
+        if( this.hasNextPage() && client != null && entity != null ) {
+            Map<String, Object> paramsMap = new HashMap<>();
+            paramsMap.put("cursor", getCursor());
+            UsergridRequest request = new 
UsergridRequest(UsergridEnums.UsergridHttpMethod.GET, 
UsergridRequest.APPLICATION_JSON_MEDIA_TYPE, client.clientAppUrl(), paramsMap, 
null, null, this.getQuery(), client.authForRequests() , entity.getType());
+            return client.sendRequest(request);
+        } else {
+            return UsergridResponse.fromError(client,"Error Loading Next 
Page.","Unable to load next page.");
+        }
+    }
+
+    @NotNull
+    public static UsergridResponse fromError(@Nullable final UsergridClient 
client, @NotNull final String errorName, @NotNull final String 
errorDescription) {
+        UsergridResponse response = new UsergridResponse();
+        response.client = client;
+        response.responseError = new 
UsergridResponseError(errorName,errorDescription);
+        return response;
+    }
+
+    @NotNull
+    public static UsergridResponse fromException(@Nullable final 
UsergridClient client, @NotNull final Exception ex) {
+        final UsergridResponse response = new UsergridResponse();
+        response.client = client;
+        final UsergridResponseError responseError = new 
UsergridResponseError();
+        responseError.setErrorDescription(ex.getMessage());
+        if( ex.getClass() != null ) {
+            responseError.setErrorName(ex.getClass().toString());
+        }
+        if( ex.getCause() != null ) {
+            responseError.setErrorException(ex.getCause().toString());
+        }
+        response.responseError = responseError;
+        return response;
+    }
+
+    @NotNull
+    public static UsergridResponse fromResponse(@NotNull final UsergridClient 
client, @NotNull final UsergridRequest request, @NotNull final okhttp3.Response 
requestResponse) {
+        UsergridResponse response;
+        JsonNode responseJson;
+        try {
+            String responseJsonString = requestResponse.body().string();
+            responseJson = JsonUtils.mapper.readTree(responseJsonString);
+        } catch ( Exception e ) {
+            return UsergridResponse.fromException(client,e);
+        }
+        if ( responseJson.has("error") )  {
+            response = new UsergridResponse();
+            response.responseError = 
JsonUtils.fromJsonNode(responseJson,UsergridResponseError.class);
+        } else {
+            response = 
JsonUtils.fromJsonNode(responseJson,UsergridResponse.class);
+        }
+        response.client = client;
+        response.responseJson = responseJson;
+        response.statusCode = requestResponse.code();
+
+        Headers responseHeaders = requestResponse.headers();
+        HashMap<String,String> headers = new HashMap<>();
+        for (int i = 0; i < responseHeaders.size(); i++) {
+            headers.put(responseHeaders.name(i),responseHeaders.value(i));
+        }
+
+        response.headers = headers;
+        response.query = request.getQuery();
+        return response;
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid-java/blob/88039bad/src/main/java/org/apache/usergrid/java/client/response/UsergridResponseError.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/usergrid/java/client/response/UsergridResponseError.java
 
b/src/main/java/org/apache/usergrid/java/client/response/UsergridResponseError.java
new file mode 100644
index 0000000..387ae56
--- /dev/null
+++ 
b/src/main/java/org/apache/usergrid/java/client/response/UsergridResponseError.java
@@ -0,0 +1,98 @@
+/*
+ * 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.apache.usergrid.java.client.response;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SuppressWarnings("unused")
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class UsergridResponseError {
+
+    @Nullable private String errorName;
+    @Nullable private String errorDescription;
+    @Nullable private String errorException;
+
+    @NotNull private final Map<String, JsonNode> properties = new HashMap<>();
+
+    public UsergridResponseError() {
+        this(null,null,null);
+    }
+    public UsergridResponseError(@Nullable final String errorName) {
+        this(errorName, null, null);
+    }
+    public UsergridResponseError(@Nullable final String errorName, @Nullable 
final String errorDescription) {
+        this(errorName,errorDescription,null);
+    }
+    public UsergridResponseError(@Nullable final String errorName, @Nullable 
final String errorDescription, @Nullable final String errorException) {
+        this.errorName = errorName;
+        this.errorDescription = errorDescription;
+        this.errorException = errorException;
+    }
+
+    @NotNull
+    @JsonAnyGetter
+    public Map<String, JsonNode> getProperties() {
+        return properties;
+    }
+
+    @JsonAnySetter
+    public void setProperty(@NotNull final String key, @NotNull final JsonNode 
value) {
+        properties.put(key, value);
+    }
+
+    @Nullable
+    @JsonProperty("error")
+    public String getErrorName() {
+        return errorName;
+    }
+
+    @JsonProperty("error")
+    public void setErrorName(@NotNull final String errorName) {
+        this.errorName = errorName;
+    }
+
+    @Nullable
+    @JsonProperty("exception")
+    public String getErrorException() {
+        return errorException;
+    }
+
+    @JsonProperty("exception")
+    public void setErrorException(@NotNull final String errorException) {
+        this.errorException = errorException;
+    }
+
+    @Nullable
+    @JsonProperty("error_description")
+    public String getErrorDescription() {
+        return errorDescription;
+    }
+
+    @JsonProperty("error_description")
+    public void setErrorDescription(@NotNull final String errorDescription) {
+        this.errorDescription = errorDescription;
+    }
+}

Reply via email to