# Usergrid Android SDK

Usergrid SDK written for Android.

The Android SDK is an extension upon the the Usergrid Java SDK with added functionality including asynchronous HTTP handling and push notifications.

## Initialization

There are two different ways of initializing the Usergrid Android SDK: 

1. The singleton pattern is both convenient and enables the developer to use a globally available and always-initialized instance of Usergrid. 

```java
Usergrid.initSharedInstance("orgId", "appId");
```

2. The Instance pattern enables the developer to manage instances of the Usergrid client independently and in an isolated fashion. The primary use-case for this is when an application connects to multiple Usergrid targets.

```java
UsergridClient client = new UsergridClient("orgId","appId");
```

_Note: Examples in this readme assume you are using the `Usergrid` shared instance. If you've implemented the instance pattern instead, simply replace `Usergrid` with your client instance variable._

## ASYNCHRONOUS operations

The examples in this readme utilize the synchronous method calls provided by the Usergrid Java SDK. 

Each RESTful operation has a matching asynchrous method within to use within the SDK for convience of use within Android applications. 

For examples of asynchronous calls, look over the sample Android applications located within the `Samples` folder.

## RESTful operations

When making any RESTful call, a `type` parameter (or `path`) is always required. Whether you specify this as an argument or in an object as a parameter is up to you.

### GET

- To get entities in a collection:

```java
UsergridResponse response = Usergrid.GET("collection");
List<UsergridEntity> entities = response.getEntities();
```

- To get a specific entity in a collection by uuid or name:

```java
UsergridResponse response = Usergrid.GET("collection","<uuid-or-name>");
UsergridEntity entities = response.entity();
```

- To get specific entities in a collection by passing a `UsergridQuery` object:

```java
UsergridQuery query = new UsergridQuery("cats").gt("weight", 2.4)
                                 	.contains("color", "bl*")
                                 .not()
                                 .eq("color", "blue")
                                 .or()
                                 .eq("color", "orange");
	
// this will build out the following query:
// select * where weight > 2.4 and color contains 'bl*' and not color = 'blue' or color = 'orange'
	
UsergridResponse response = Usergrid.GET(query);
List<UsergridEntity> entities = response.getEntities();
```

### POST and PUT

POST and PUT requests both require a JSON body payload. You can pass either a Java object or a `UsergridEntity` instance. While the former works in principle, best practise is to use a `UsergridEntity` wherever practical. When an entity has a uuid or name property and already exists on the server, use a PUT request to update it. If it does not, use POST to create it.

- To create a new entity in a collection (**POST**):

```java
HashMap<String,String> propertyMap = new HashMap<>();
propertyMap.put("cuisine","pizza");
UsergridEntity entity = new UsergridEntity("restaurant","Dino's Deep Dish", propertyMap);	
Usergrid.POST(entity); // entity should now have a uuid property and be created
	
// you can also POST an array of entities:
	
HashMap<String,String> propertyMap = new HashMap<>();
propertyMap.put("cuisine","pizza");

ArrayList<UsergridEntity> entities = new ArrayList<>();
entities.add(new UsergridEntity("restaurant","Dino's Deep Dish", propertyMap));
entities.add(new UsergridEntity("restaurant","Pizza da Napoli", propertyMap));
UsergridResponse response = Usergrid.POST(entities);
List<UsergridEntity> responseEntities = response.getEntities(); // responseEntities should now contain now valid posted entities.
```

- To update an entity in a collection (**PUT**):

```java
HashMap<String,String> propertyMap = new HashMap<>();
propertyMap.put("cuisine","pizza");
UsergridEntity entity = new UsergridEntity("restaurant","Dino's Deep Dish", propertyMap);	
UsergridResponse response = Usergrid.POST(entity);
if( response.ok() ) {
	entity.putProperty("owner","Mia Carrara");
	Usergrid.PUT(entity); // entity now has the property 'owner'
}
	
// or update a set of entities by passing a UsergridQuery object

HashMap<String,String> propertiesToUpdate = new HashMap<>();
propertiesToUpdate.put("cuisine","pizza");
UsergridQuery query = new UsergridQuery("restaurants").eq("cuisine","italian");

UsergridResponse response = Usergrid.PUT(query, propertiesToUpdate);
	
    /* the first 10 entities matching this query criteria will be updated:
    e.g.:
        [
            {
                "type": "restaurant",
                "restaurant": "Il Tarazzo",
                "cuisine": "italian",
                "keywords": ["pasta"]
            },
            {
                "type": "restaurant",
                "restaurant": "Cono Sur Pizza & Pasta",
                "cuisine": "italian",
                "keywords": ["pasta"]
            }
        ]
    */
```

### DELETE

DELETE requests require either a specific entity or a `UsergridQuery` object to be passed as an argument.

- To delete a specific entity in a collection by uuid or name:

```java
UsergridResponse response = Usergrid.DELETE("collection", "<uuid-or-name>"); // if successful, entity will now be deleted
```

- To specific entities in a collection to delete by passing a `UsergridQuery` object:

```java
UsergridQuery query = new UsergridQuery("cats").eq("color","black").or().eq("color","white");
	
// this will build out the following query:
// select * where color = 'black' or color = 'white'
	
UsergridResponse response = Usergrid.DELETE(query); // the first 10 entities matching this query criteria will be deleted
```

## Entity operations and convenience methods

`UsergridEntity` has a number of helper/convenience methods to make working with entities more convenient.

### reload()

Reloads the entity from the server:

```java
entity.reload(); // entity is now reloaded from the server
```

### save()

Saves (or creates) the entity on the server:


```java
entity.putProperty("aNewProperty","A new value");
entity.save(); // entity is now updated on the server
```

### remove()

Deletes the entity from the server:

```java
entity.remove(); // entity is now deleted on the server and the local instance should be destroyed
```

## Authentication, current user, and auth-fallback

### appAuth and authenticateApp()

`Usergrid` can use the app client ID and secret that were passed upon initialization and automatically retrieve an app-level token for these credentials.

```java
Usergrid.setAppAuth(new UsergridAppAuth("<client-id>", "<client-secret>"));
Usergrid.authenticateApp(); // Usergrid.appAuth is authenticated automatically when this call is successful
```

### currentUser, userAuth,  and authenticateUser()

`Usergrid` has a special `currentUser` property. 

By default, when calling `authenticateUser()`, `.currentUser` will be set to this user if the authentication flow is successful.

```java
UsergridUserAuth userAuth = new UsergridUserAuth("<username>","<password>");
Usergrid.authenticateUser(userAuth); // Usergrid.currentUser is set to the authenticated user and the token is stored within that context
```
    
If you want to utilize authenticateUser without setting as the current user, simply pass a `false` boolean value as the second parameter:

```java
UsergridUserAuth userAuth = new UsergridUserAuth("<username>","<password>");
Usergrid.authenticateUser(userAuth,false); // user is authenticated but Usergrid.currentUser is not set.
```

### authMode

Auth-mode defines what the client should pass in for the authorization header. 

By default, `Usergrid.authMode` is set to `.User`, when a `Usergrid.currentUser` is present and authenticated, an API call will be performed using the token for the user. 

If `Usergrid.authMode` is set to `.None`, all API calls will be performed unauthenticated. 

If instead `Usergrid.authMode` is set to `.App`, the API call will instead be performed using client credentials, _if_ they're available (i.e. `authenticateApp()` was performed at some point). 

### usingAuth()

At times it is desireable to have complete, granular control over the authentication context of an API call. 

To facilitate this, the passthrough function `.usingAuth()` allows you to pre-define the auth context of the next API call.

```java
// assume Usergrid.authMode = UsergridAuthMode.NONE.

Map<String, String> permissionsMap = new HashMap<>();
permissionsMap.put("permission","get,post,put,delete:/**");
UsergridResponse response = Usergrid.usingAuth(Usergrid.getAppAuth()).POST("roles/guest/permissions",permissionsMap);

// here we've temporarily used the client credentials to modify permissions
// subsequent calls will not use this auth context
```

## User operations and convenience methods

`UsergridUser` has a number of helper/convenience methods to make working with user entities more convenient. If you are _not_ utilizing the `Usergrid` shared instance, you must pass an instance of `UsergridClient` as the first argument to any of these helper methods.
    
### create()

Creating a new user:

```java
UsergridUser user = new UsergridUser("username","password");
user.create(); // user has now been created and should have a valid uuid
```

### login()

A simpler means of retrieving a user-level token:

```java
user.login("username","password"); // user is now logged in
```

### logout()

Logs out the selected user. You can also use this convenience method on `Usergrid.currentUser`.

```java
user.logout(); // user is now logged out
```

### resetPassword()

Resets the password for the selected user.

```java
// if it was done correctly, the new password will be changed
user.resetPassword("oldPassword", "newPassword");
```

### UsergridUser.CheckAvailable()

This is a class (static) method that allows you to check whether a username or email address is available or not.

```java
boolean available = UsergridUser.checkAvailable("email", null); // 'available' == whether an email already exists for a user

available = UsergridUser.checkAvailable(null, "username"); // 'available' == whether an username already exists for a user

available = UsergridUser.checkAvailable("email", "username"); // 'available' == whether an email or username already exist for a user
```

## Querying and filtering data

### UsergridQuery initialization

The `UsergridQuery` class allows you to build out complex query filters using the Usergrid [query syntax](http://docs.apigee.com/app-services/content/querying-your-data).

The first parameter of the `UsergridQuery` builder pattern should be the collection (or type) you intend to query. You can either pass this as an argument, or as the first builder object:

```java
UsergridQuery query = new UsergridQuery("cats");
// or
UsergridQuery query = new UsergridQuery().collection("cats");
```

You then can layer on additional queries:

```java
UsergridQuery query = new UsergridQuery("cats").gt("weight",2.4).contains("color","bl*")
                                 .not()
                                 .eq("color","white")
                                 .or()
                                 .eq("color","orange");
```

You can also adjust the number of results returned:

```java
UsergridQuery query = new UsergridQuery("cats").eq("color","black").limit(100);
                                 
// returns a maximum of 100 entities
```

And sort the results:

```java
UsergridQuery query = new UsergridQuery("cats").eq("color","black").limit(100).asc("name")
                                 
// sorts by 'name', ascending
```

And you can do geo-location queries:

```java
UsergridQuery query = new UsergridQuery("devices").locationWithin(<distance>, <lat>, <long>);
```

### Using a query in a request

Queries can be passed as parameters to GET, PUT, and DELETE requests:

```java
// Gets entities matching the query.
Usergrid.GET(query);

// Updates the entities matching the query with the new property.
Usergrid.PUT(query, Collections.singletonMap("aNewProperty","A new value"));

// Deletes entities of a given type matching the query.
Usergrid.DELETE(query);
```
### List of query builder objects

`type("string")`

> The collection name to query

`collection("string")`

> An alias for `type`

`eq("key","value")` or 
`equals("key","value")` or 
`filter("key","value")` 

> Equal to (e.g. `where color = 'black'`)

`contains("key","value")` or
`containsString("key","value")` or
`containsWord("key","value")`

> Contains a string (e.g.` where color contains 'bl*'`)

`gt("key","value")` or
`greaterThan("key","value")`

> Greater than (e.g. `where weight > 2.4`)

`gte("key","value")` or 
`greaterThanOrEqual("key","value")`

> Greater than or equal to (e.g. `where weight >= 2.4`)

`lt("key","value")` or `lessThan("key","value")`

> Less than (e.g. `where weight < 2.4`)

`lte("key","value")` or `lessThanOrEqual("key","value")`

> Less than or equal to (e.g. `where weight <= 2.4`)

`not()`

> Negates the next block in the builder pattern, e.g.:

```java
UsergridQuery query = new UsergridQuery("cats").not().eq("color","black");
// select * from cats where not color = 'black'
```

`and()`

> Joins two queries by requiring both of them. `and` is also implied when joining two queries _without_ an operator. E.g.:

```java
UsergridQuery query = new UsergridQuery("cats").eq("color","black").eq("fur","longHair");
// is identical to:
UsergridQuery query = new UsergridQuery("cats").eq("color","black").and().eq("fur","longHair");
```

`or()`

> Joins two queries by requiring only one of them. `or` is never implied. e.g.:

```java
UsergridQuery query = new UsergridQuery("cats").eq("color","black").or().eq("color", "white");
```
    
> When using `or()` and `and()` operators, `and()` joins will take precedence over `or()` joins. You can read more about query operators and precedence [here](http://docs.apigee.com/api-baas/content/supported-query-operators-data-types).

`locationWithin(distanceInMeters, latitude, longitude)`

> Returns entities which have a location within the specified radius. Arguments can be `float` or `int`.

`asc("key")` or `ascending("key")`

> Sorts the results by the specified property, ascending

`desc("key")` or `descending("key")`

> Sorts the results by the specified property, descending

`sort("key",UsergridQuerySortOrder.ASC)`

> Sorts the results by the specified property, in the specified `UsergridQuerySortOrder` (`.ASC` or `.DESC`).
 
`limit(int)`

> The maximum number of entities to return

`cursor("string")`

> A pagination cursor string

`fromString("query string")`

> A special builder property that allows you to input a pre-defined query string. All builder properties will be ignored when this property is defined. For example:
    
```java
UsergridQuery query = new UsergridQuery().fromString("select * where color = 'black' order by name asc");
```

## UsergridResponse object

`UsergridResponse` is the core class that handles both successful and unsuccessful HTTP responses from Usergrid. 

If a request is successful, any entities returned in the response will be automatically parsed into `UsergridEntity` objects and pushed to the `entities` property.

If a request fails, the `error` property will contain information about the problem encountered.

### ok

You can check `UsergridResponse.ok`, a `Bool` value, to see if the response was successful. Any status code `< 400` returns true.

```java
UsergridResponse response = Usergrid.GET("collection");
if( response.ok() ) {
    // woo!
}
```
    
### entity, entities, user, users, first, last

Depending on the call you make, any entities returned in the response will be automatically parsed into `UsergridEntity` objects and pushed to the `entities` property. If you're querying the `users` collection, these will also be `UsergridUser` objects, a subclass of `UsergridEntity`.

- `.first()` returns the first entity in an array of entities; `.entity()` is an alias to `.first()`. If there are no entities, both of these will be undefined.

- `.last()` returns the last entity in an array of entities; if there is only one entity in the array, this will be the same as `.first()` _and_ `.entity()`, and will be undefined if there are no entities in the response.

- `.getEntities()` will either be an array of entities in the response, or an empty array.

- `.user()` is a special alias for `.entity()` for when querying the `users()` collection. Instead of being a `UsergridEntity`, it will be its subclass, `UsergridUser`.

- `.users()` is the same as `.user()`, though behaves as `.getEntities()` does by returning either an array of UsergridUser objects or an empty array.

Examples:

```java
UsergridResponse response = Usergrid.GET("collection");
    // you can access:
    //     response.getEntities() (the returned entities)
    //     response.first() (the first entity)
    //     response.entity() (same as response.first)
    //     response.last() (the last entity returned)

UsergridResponse response = Usergrid.GET("collection","<uuid-or-name>");
    // you can access:
    //     response.entity() (the returned entity) 
    //     response.getEntities() (containing only the returned entity)
    //     response.first() (same as response.entity)
    //     response.last() (same as response.entity)

UsergridResponse response = Usergrid.GET("users");
    // you can access:
    //     response.users() (the returned users)
    //     response.getEntities() (same as response.users)
    //     response.user() (the first user)    
    //     response.entity() (same as response.user)   
    //     response.first() (same as response.user)  
    //     response.last() (the last user)

UsergridResponse response = Usergrid.GET("users","<uuid-or-name>");
    // you can access;
    //     response.users() (containing only the one user)
    //     response.getEntities() (same as response.users)
    //     response.user() (the returned user)    
    //     response.entity() (same as response.user)   
    //     response.first() (same as response.user)  
    //     response.last() (same as response.user)  
```

## Connections

Connections can be managed using `Usergrid.connect()`, `Usergrid.disconnect()`, and `Usergrid.getConnections()`, or entity convenience methods of the same name. 

When retrieving connections via `Usergrid.getConnections()`, you can pass in a optional `UsergridQuery` object in order to filter the connectioned entities returned.

### Connect

Create a connection between two entities:

```java
Usergrid.connect(entity1, "relationship", entity2); // entity1 now has an outbound connection to entity2
```

### Retrieve Connections

Retrieve outbound connections:

```java
Usergrid.getConnections(UsergridDirection.OUT, entity1, "relationship");
    // entities is an array of entities that entity1 is connected to via 'relationship'
    // in this case, we'll see entity2 in the array
```

Retrieve inbound connections:

```java
Usergrid.getConnections(UsergridDirection.IN, entity2, "relationship");
    // entities is an array of entities that connect to entity2 via 'relationship'
    // in this case, we'll see entity1 in the array
```

### Disconnect

Delete a connection between two entities:

```java
Usergrid.disconnect(entity1, "relationship", entity2);
    // entity1's outbound connection to entity2 has been destroyed
```

## Custom UsergridEntity Subclasses

Creating custom subclasses of the base `UsergridEntity` class (just like `UsergridUser` and `UsergridDevice`) is possible.

- To do so, subclass `UsergridEntity` and implement the required methods:

```java
public class ActivityEntity extends UsergridEntity {
	public static final String ACTIVITY_ENTITY_TYPE = "activity";
	
   public ActivityEntity(){
       super(ACTIVITY_ENTITY_TYPE);
   }
}
```
- You will also need to register the custom subclass:

```java
Usergrid.initSharedInstance("orgId","appId");
UsergridEntity.mapCustomSubclassToType("activity", ActivityEntity.class);
```

By registering your custom subclass, the `UsergridEntity` and `UsergridResponse` classes are able to generate instances of these classes based on the an entities `type`.

In the above example, entities which have a `type` value of `activity` can now be cast as `ActivityEntity` objects. e.g.:

```java
UsergridResponse response = Usergrid.GET("activity");
ActivityEntity activityEntity = (ActivityEntity)response.entity();
```
