Giter VIP home page Giter VIP logo

vault's Introduction

Vault

Build Status

Vault is an Android library that simplifies persistence of data from Contentful via SQLite. It lets you define Java representations for your Contentful models. Then, at compile-time it will create a corresponding database schema by generating all the required boilerplate code and injecting it to the classpath. It is also bundled with a complementary lightweight runtime which exposes a simple ORM-like API for pulling resources from the generated database.

Setup

Grab via Maven:

<dependency>
  <groupId>com.contentful.vault</groupId>
  <artifactId>compiler</artifactId>
  <version>0.9.10</version>
</dependency>
<dependency>
  <groupId>com.contentful.vault</groupId>
  <artifactId>core</artifactId>
  <version>0.9.10</version>
</dependency>

or Gradle:

apt 'com.contentful.vault:compiler:0.9.10'
compile 'com.contentful.vault:core:0.9.10'

Note for Gradle users, make sure to use the android-apt Gradle plugin, which lets you configure compile-time only dependencies.

Snapshots of the development version are available in Sonatype's snapshots repository.

Models & Fields

Models are defined by declaring a subclass of the Resource class. Annotate the class with @ContentType, which takes the Content Type's ID as its value.

Fields are defined by annotating class attributes with the @Field annotation.

@ContentType("cat")
public class Cat extends Resource {
  @Field public String name;
  @Field public Cat bestFriend;
  @Field public Asset image;
}

By default, the name of the attribute will be used as the field's ID, but can also be specified explicitly:

@Field("field-id-goes-here") 
public String someField; 

Field ids are escaped and so can be used regularly, however when making queries with a WHERE condition it is up to the caller to escape the field name in case it is a reserved keyword. For example, consider the following model:

@ContentType("...")
public class Foo extends Resource {
  @Field public String order;
}

Since order is a reserved SQLite keyword, in order to make a query which references that field here is how to escape it:

vault.fetch(Foo.class)
    .where("`" + Foo$Fields.ORDER "` = ?", "bar")
    .first();

Spaces

Spaces can be defined by declaring a class annotated with the @Space annotation. It is required to specify the Space ID, an array of model classes and an array of locale codes you wish to persist:

@Space(
    value = "cfexampleapi",
    models = { Cat.class },
    locales = { "en-US", "tlh" }
)
public class DemoSpace { }

Synchronization

Once a Space is defined, invoke Vault to sync the local database with the remote state:

// Client
CDAClient client = CDAClient.builder()
    .setSpace("cfexampleapi");
    .setToken("b4c0n73n7fu1");
    .build();

// Sync
Vault.with(context, DemoSpace.class).requestSync(client);

Vault will use a worker thread to request incremental updates from the Sync API and reflect the remote changes to its database. Once sync is completed, Vault will fire a broadcast with the action Vault.ACTION_SYNC_COMPLETE.

Alternatively, you can provide a SyncCallback which will be invoked once sync is completed, but make sure to cancel it according to its host lifecycle events:

class SomeActivity extends Activity {
  SyncCallback callback;
  
  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    Vault.with(this, DemoSpace.class).requestSync(client, callback = new SyncCallback() {
      @Override public void onResult(SyncResult result) {
        if (result.isSuccessful()) {
          // Success \o/
        } else {
          // Failure
        }
      }
    });
  }
  
  @Override protected void onDestroy() {
    Vault.cancel(callback);
    super.onDestroy();
  }
}

Similarly, if you're using RxJava, you can be notified of sync results via an Observable:

Vault.observeSyncResults() // returns Observable<SyncResult>

Queries

Vault provides a wrapper around its generated database which can be easily used to fetch persisted objects, some examples:

Vault vault = Vault.with(context, DemoSpace.class);

// Fetch the first Cat
vault.fetch(Cat.class)
    .first();
    
// Fetch the most recently updated Cat
vault.fetch(Cat.class)
    .order(Cat$Fields.UPDATED_AT + " DESC")
    .first();

// Fetch a Cat with a specific name
vault.fetch(Cat.class)
    .where(Cat$Fields.NAME + " = ?", "Nyan Cat")
    .first();
    
// Fetch all Cats, ordered by creation date:
vault.fetch(Cat.class)
    .order(Cat$Fields.CREATED_AT)
    .all();

// Fetch all Cats, using the Klingon locale:
vault.fetch(Cat.class)
    .all("tlh");

If you're using RxJava, you can create queries with the observe() method, for example:

vault.observe(Cat.class)
    .where(Cat$Fields.NAME + " = ?", "Happy Cat")
    .all() // returns Observable<Cat>

The above example creates an Observable that subscribes and observes on the same thread initiating the query, so make sure to change that according to your requirements. A typical use-case would be:

vault.observe(Cat.class)
    .all()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())

Migrations

Whenever changes are introduced to any of the previously used models, a migration has to be applied. Simply increment the version number for your space to trigger a migration:

@Space(value = "cfexampleapi", models = { Cat.class }, dbVersion = 2)
public class DemoSpace { }

Note: this will delete any previously persisted data.

Database pre-seeding

Depending on the amount of content in a given space, initial synchronization might take some time. For that we've added support to pre-seed the database with static content. In order to do that one has to add an existing Vault database file into the assets folder of the project, and then reference this file through the copyPath attribute, for example:

@Space(value = "foo", models = { Bar.class }, copyPath = "vault_file_name.db")
public class FooSpace { }

Note that in order to add this functionality to an already shipped app, the dbVersion value has to be increased, as it causes invalidation of any pre-existing content.

ProGuard

Grab the ProGuard configuration file and apply to your project.

Documentation

Javadoc is available here.

License

Copyright 2015 Contentful, GmbH.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

vault's People

Contributors

tomxor avatar neonichu avatar

Watchers

James Cloos avatar dev.with avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.