Cursor操作をﾁｮｯﾄだけ楽にする

# Cursor操作をﾁｮｯﾄだけ楽にする

Androidを開発していたら必ずと言っていいほどCursorが出てきますね。
例えば、DBにqueryしてCursorのインスタンスを取得して、そのcursorをcursor.moveToFirstでポジションを移動して、getColumnIndexでindexを取得してからgetString, getInt等で値を取得して、最後にはちゃんとcursorをcloseしてなどなど...。
こんな感じでしょうか。

```java
Cursor cursor = null;
try {
    cursor = getCursor(...);
    if (cursor != null && cursor.moveToFirst()) {
        int columnIndex = cursor.getColumnIndex(MediaStore.Images.Media._ID);
        Long id = cursor.getLong(fieldIndex);
        //以下、略...
    }
} finally {
    if (cursor != null) {
        cursor.close();
    }
}
```

毎度毎度同じコード書くのは辛いので、このようなボイラーテンプレートなコードは自動生成するに限ります。
という訳で、Cursorを操作をﾁｮｯﾄだけ楽にするために、Cursor<->Entity変換を行うライブラリ__Curson__を作りました。

## How to install ?
build.gradleに下記を記述してください

```groovy
buildscript {
  repositories {
    mavenCentral()
   }
  dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  }
}

apply plugin: 'com.neenbedankt.android-apt'

dependencies {
    compile 'com.github.dkajiwara:curson:1.0.2'
    apt 'com.github.dkajiwara:curson-compiler:1.0.2'
}
```

## How to use?
使い方は簡単です、Cursorに対応するEntityオブジェクトを作成してください。
次に、作成したEntityオブジェクトとCursorのインスタンスを```Cursor.fromCursor()```を引数に渡してください。
具体的なコードを書いたほうが分かりやすいと思いますので、下記に端末内の画像取得する場合の例を載せています。

```java
public class Image {
    @CursorRow(ImageColumns.BUCKET_DISPLAY_NAME/*カラム名*/)
    String bucketDisplayName;

    @CursorRow(ImageColumns.BUCKET_ID)
    String bucketId;
}

public class ImageManager {
    public List<Image> getImages() {
        Cursor cursor = query...//image取得する
        return Curson.fromCursor(cursor, Image.class);
    }

    public Image getImage() {
        Cursor cursor = query...//image取得する
        return Curson.fromCursor(
                cursor,
                Image.class /*作成したEntityクラスを指定する*/,
                0 /*cursorのpositionを指定する*/);
    }
}
```

上記の例では、Cursorのcloseを呼んでいません。これは```Cursor.fromCursor()```ではデフォルトで```cursor.close()```を呼んでいます。なので、変換時にCursorのcloseをしたくない場合は、メソッド```Curson#fromCursor(Cursor, Class, int, boolean)```を使い、引数(boolean)に__false__を指定してください。
また、CursorRowアノテーションは下記の型をサポートしています。

 * byte[]
 * int / Integer
 * double / Double
 * float / Float
 * short / Short
 * String


## Other
Cursorオブジェクトへの変換として```Cursor.toCursor()```メソッドをサポートしています。EntityオブジェクトからCursorオブジェクトへの変換なのであまり使う機会は少ないかと思いますが、UnitTest時のContentProviderのモックで使用するとﾁｮｯﾄだけ楽になります。

```java

public class ExContentProvider extends ContentProvider {
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        List<Sample> list = new ArrayList<>();
        list.add(new Sample(1, 100000000L, "description1", "title1", 1));
        list.add(new Sample(2, 100000001L, "description2", "title2", 1));
        list.add(new Sample(3, 100000002L, "description3", "title3", 0));
        list.add(new Sample(4, 100000003L, "description4", "title4", 1));
        return Curson.toCursor(list, Sample.class);
    }
}
```

## End
今回、ライブラリの使い方のみで中身の実装に関しては触れていませんが、雑に説明するとコンパイル時にアノテーションプロセッシングを使用してEntityクラスから下記のようなクラスを生成しています。実行時には内部でこのクラスを呼び出すことでCursor<->Entityオブジェクトの変換を行う仕組みとなっています。

```java
public class Sample$$CursonEntityBinder implements CursorBinder<Sample> {
  @Override
  public Sample bind(Cursor cursor) {
    final int idIndex = cursor.getColumnIndex("_id");

    Sample sample = new Sample();
    sample.id = cursor.getInt(idIndex);

    return sample;
  }
  //いろいろ省略...
}
```

## Reference
Curson
https://github.com/dkajiwara/Curson