{"action":"created","comment":{"url":"https://api.github.com/repos/realm/realm-java/pulls/comments/29836045","id":29836045,"diff_hunk":"@@ -0,0 +1,548 @@\n+/*\n+ * Copyright 2014 Realm Inc.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ * http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+\n+package io.realm.android;\n+\n+import android.content.ContentResolver;\n+import android.database.CharArrayBuffer;\n+import android.database.ContentObserver;\n+import android.database.Cursor;\n+import android.database.DataSetObservable;\n+import android.database.DataSetObserver;\n+import android.net.Uri;\n+import android.os.Bundle;\n+\n+import io.realm.Realm;\n+import io.realm.RealmChangeListener;\n+import io.realm.RealmResults;\n+import io.realm.internal.ColumnType;\n+import io.realm.internal.TableOrView;\n+\n+/**\n+ * This classes exposes {@link io.realm.RealmResults} as a cursor.\n+ * <p>\n+ * It is possible to traverse links using dot notation to access data in referenced objects, ie.\n+ * {@code cursor.getInt(\"foo.bar\"} will return the integer from the {@code bar} field in the {@code foo} object\n+ * referenced the class represented by the RealmResult.\n+ * <p>\n+ * Many Android framework classes require the presences of an \"_id\" field. Instead of adding such a field to your\n+ * model class it is instead possible to use {@link #setIdColumn(String)}.\n+ * <p>\n+ * A RealmCursor has the same thread restrictions as RealmResults, so it is not possible to move a RealmCursor between\n+ * threads.\n+ * <p>\n+ * TODO How to handle RealmList? getString(\"realmList[0].name)\"?\n+ * TODO How to iterate a RealmList?\n+ */\n+public class RealmCursor implements Cursor {\n+\n+    private static final String DEFAULT_ID_COLUMN = \"_id\";\n+\n+    private final Realm realm;\n+    private TableOrView table;\n+    private int rowIndex;\n+    private boolean closed;\n+    private long idColumnIndex = -1; // Column index for the \"_id\" field. -1 means it hasn't been set\n+    private final DataSetObservable dataSetObservable = new DataSetObservable();\n+    private RealmChangeListener changeListener = new RealmChangeListener() {\n+        @Override\n+        public void onChange() {\n+            if (dataSetObservable != null) {\n+                dataSetObservable.notifyChanged(); // TODO Should be replaced with something more fine grained.\n+            }\n+        }\n+    };\n+\n+    /**\n+     * Exposes a RealmResults object as a cursor. Use {@link RealmResults#getCursor()} instead of this\n+     * constructor\n+     *\n+     * @param table Table view representing the query results.\n+     */\n+    public RealmCursor(Realm realm, TableOrView table) {\n+        this.table = table;\n+        this.rowIndex = -1;\n+        this.realm = realm;\n+        realm.addChangeListener(changeListener);\n+    }\n+\n+    /**\n+     * {@inheritDoc}\n+     */\n+    @Override\n+    public int getCount() {\n+        return (int) table.size();\n+    }\n+\n+    /**\n+     * {@inheritDoc}\n+     */\n+    @Override\n+    public int getPosition() {\n+        return rowIndex;\n+    }\n+\n+    /**\n+     * {@inheritDoc}\n+     */\n+    @Override\n+    public final boolean move(int offset) {\n+        return moveToPosition(rowIndex + offset);\n+    }\n+\n+    /**\n+     * {@inheritDoc}\n+     */\n+    @Override\n+    public boolean moveToPosition(int position) {\n+        // Verify position is not post the end of the cursor.\n+        final int count = getCount();\n+        if (position >= count) {\n+            rowIndex = count;\n+            return false;\n+        }\n+\n+        // Verify position is not before the start of the cursor.\n+        if (position < 0) {\n+            rowIndex = -1;\n+            return false;\n+        }\n+\n+        rowIndex = position;\n+        return true;\n+    }\n+\n+    /**\n+     * {@inheritDoc}\n+     */\n+    @Override\n+    public boolean moveToFirst() {\n+        return moveToPosition(0);","path":"realm/src/main/java/io/realm/android/RealmCursor.java","position":133,"original_position":133,"commit_id":"c659a9901738be60a783bfa897c24f640d92806c","original_commit_id":"c659a9901738be60a783bfa897c24f640d92806c","user":{"login":"bmunkholm","id":1215687,"avatar_url":"https://avatars.githubusercontent.com/u/1215687?v=3","gravatar_id":"","url":"https://api.github.com/users/bmunkholm","html_url":"https://github.com/bmunkholm","followers_url":"https://api.github.com/users/bmunkholm/followers","following_url":"https://api.github.com/users/bmunkholm/following{/other_user}","gists_url":"https://api.github.com/users/bmunkholm/gists{/gist_id}","starred_url":"https://api.github.com/users/bmunkholm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bmunkholm/subscriptions","organizations_url":"https://api.github.com/users/bmunkholm/orgs","repos_url":"https://api.github.com/users/bmunkholm/repos","events_url":"https://api.github.com/users/bmunkholm/events{/privacy}","received_events_url":"https://api.github.com/users/bmunkholm/received_events","type":"User","site_admin":false},"body":"Reduce to as there is no reason to do all the parameter checks:\r\n````\r\nrowIndex = 0;\r\nreturn true;\r\n````","created_at":"2015-05-07T09:17:48Z","updated_at":"2015-05-07T09:17:48Z","html_url":"https://github.com/realm/realm-java/pull/1090#discussion_r29836045","pull_request_url":"https://api.github.com/repos/realm/realm-java/pulls/1090","_links":{"self":{"href":"https://api.github.com/repos/realm/realm-java/pulls/comments/29836045"},"html":{"href":"https://github.com/realm/realm-java/pull/1090#discussion_r29836045"},"pull_request":{"href":"https://api.github.com/repos/realm/realm-java/pulls/1090"}}},"pull_request":{"url":"https://api.github.com/repos/realm/realm-java/pulls/1090","id":34808074,"html_url":"https://github.com/realm/realm-java/pull/1090","diff_url":"https://github.com/realm/realm-java/pull/1090.diff","patch_url":"https://github.com/realm/realm-java/pull/1090.patch","issue_url":"https://api.github.com/repos/realm/realm-java/issues/1090","number":1090,"state":"open","locked":false,"title":"[WIP] RealmCursor","user":{"login":"cmelchior","id":406066,"avatar_url":"https://avatars.githubusercontent.com/u/406066?v=3","gravatar_id":"","url":"https://api.github.com/users/cmelchior","html_url":"https://github.com/cmelchior","followers_url":"https://api.github.com/users/cmelchior/followers","following_url":"https://api.github.com/users/cmelchior/following{/other_user}","gists_url":"https://api.github.com/users/cmelchior/gists{/gist_id}","starred_url":"https://api.github.com/users/cmelchior/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cmelchior/subscriptions","organizations_url":"https://api.github.com/users/cmelchior/orgs","repos_url":"https://api.github.com/users/cmelchior/repos","events_url":"https://api.github.com/users/cmelchior/events{/privacy}","received_events_url":"https://api.github.com/users/cmelchior/received_events","type":"User","site_admin":false},"body":"Fixes #438 \r\n\r\n**Missing**\r\n- [x] Missing unit tests\r\n- [x] JavaDoc\r\n- [ ] Figure out how to handle RealmLists\r\n- [ ] Make Gradle respect @inheritDoc \r\n\r\n\r\n**Description**\r\nThis adds a Cursor implementation for Realm data. The main challenge is mapping the very limited types in SQLite to the more expressive types in Realm.\r\n\r\nThe current approach is to respect the Cursor interface as much as possible as that is what will be exposed in ContentProviders and other framework classes.\r\n\r\nThis has the following implications:\r\n```\r\n// Simple types\r\nBoolean:  becomes a Cursor.INTEGER and will return 0 or 1 when calling Cursor.getInt()\r\nDate: becomes a Cursor.INTEGER. getLong() return ms. since epoch. getInt() and getShort() will throw exception.\r\n\r\n// Links: dot.notation will work as normal\r\ncursor.getString(\"foo.columnString\")\r\n\r\n// LinkLists: No immediately good solution is available. Suggestion is adding support  for the following syntax. Disallowing accessing RealmLists might also be an option as it doesn't map well to a table layout anyway?\r\nint length = cursor.getInt(\"bar.size()\"); // Get length of list\r\ncursor.getString(\"bar[1].columnString\"); // Return element at position 1. Can use length to iterate\r\n\r\n// Alternative solution: Cursor supports a method called Cursor.getExtras(), ie. the size() method could instead be\r\nint length = cursor.getExtras().getInt(\"bar.size()\");\r\n```\r\n\r\nI have a single new method ```setIdColumn(String columnName)``` that creates a virtual \"_id\" field used by many framework classes. This should be acceptable as it is defined when the Cursor is created and the developer know it is a ReamCursor. Adding other nice methods like ```getDate()``` should be avoided as client code should only interact with the cursor using the Interface.\r\n\r\n@emanuelez @kneth @bmunkholm \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n","created_at":"2015-05-06T11:19:06Z","updated_at":"2015-05-07T09:17:48Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c6964c4e4be79ee77a055dc5ee9bbd9aa9c17d5b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/realm/realm-java/pulls/1090/commits","review_comments_url":"https://api.github.com/repos/realm/realm-java/pulls/1090/comments","review_comment_url":"https://api.github.com/repos/realm/realm-java/pulls/comments{/number}","comments_url":"https://api.github.com/repos/realm/realm-java/issues/1090/comments","statuses_url":"https://api.github.com/repos/realm/realm-java/statuses/c659a9901738be60a783bfa897c24f640d92806c","head":{"label":"realm:cm-cursor","ref":"cm-cursor","sha":"c659a9901738be60a783bfa897c24f640d92806c","user":{"login":"realm","id":7575099,"avatar_url":"https://avatars.githubusercontent.com/u/7575099?v=3","gravatar_id":"","url":"https://api.github.com/users/realm","html_url":"https://github.com/realm","followers_url":"https://api.github.com/users/realm/followers","following_url":"https://api.github.com/users/realm/following{/other_user}","gists_url":"https://api.github.com/users/realm/gists{/gist_id}","starred_url":"https://api.github.com/users/realm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/realm/subscriptions","organizations_url":"https://api.github.com/users/realm/orgs","repos_url":"https://api.github.com/users/realm/repos","events_url":"https://api.github.com/users/realm/events{/privacy}","received_events_url":"https://api.github.com/users/realm/received_events","type":"Organization","site_admin":false},"repo":{"id":4084908,"name":"realm-java","full_name":"realm/realm-java","owner":{"login":"realm","id":7575099,"avatar_url":"https://avatars.githubusercontent.com/u/7575099?v=3","gravatar_id":"","url":"https://api.github.com/users/realm","html_url":"https://github.com/realm","followers_url":"https://api.github.com/users/realm/followers","following_url":"https://api.github.com/users/realm/following{/other_user}","gists_url":"https://api.github.com/users/realm/gists{/gist_id}","starred_url":"https://api.github.com/users/realm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/realm/subscriptions","organizations_url":"https://api.github.com/users/realm/orgs","repos_url":"https://api.github.com/users/realm/repos","events_url":"https://api.github.com/users/realm/events{/privacy}","received_events_url":"https://api.github.com/users/realm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/realm/realm-java","description":"Realm is a mobile database: a replacement for SQLite & ORMs","fork":false,"url":"https://api.github.com/repos/realm/realm-java","forks_url":"https://api.github.com/repos/realm/realm-java/forks","keys_url":"https://api.github.com/repos/realm/realm-java/keys{/key_id}","collaborators_url":"https://api.github.com/repos/realm/realm-java/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/realm/realm-java/teams","hooks_url":"https://api.github.com/repos/realm/realm-java/hooks","issue_events_url":"https://api.github.com/repos/realm/realm-java/issues/events{/number}","events_url":"https://api.github.com/repos/realm/realm-java/events","assignees_url":"https://api.github.com/repos/realm/realm-java/assignees{/user}","branches_url":"https://api.github.com/repos/realm/realm-java/branches{/branch}","tags_url":"https://api.github.com/repos/realm/realm-java/tags","blobs_url":"https://api.github.com/repos/realm/realm-java/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/realm/realm-java/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/realm/realm-java/git/refs{/sha}","trees_url":"https://api.github.com/repos/realm/realm-java/git/trees{/sha}","statuses_url":"https://api.github.com/repos/realm/realm-java/statuses/{sha}","languages_url":"https://api.github.com/repos/realm/realm-java/languages","stargazers_url":"https://api.github.com/repos/realm/realm-java/stargazers","contributors_url":"https://api.github.com/repos/realm/realm-java/contributors","subscribers_url":"https://api.github.com/repos/realm/realm-java/subscribers","subscription_url":"https://api.github.com/repos/realm/realm-java/subscription","commits_url":"https://api.github.com/repos/realm/realm-java/commits{/sha}","git_commits_url":"https://api.github.com/repos/realm/realm-java/git/commits{/sha}","comments_url":"https://api.github.com/repos/realm/realm-java/comments{/number}","issue_comment_url":"https://api.github.com/repos/realm/realm-java/issues/comments{/number}","contents_url":"https://api.github.com/repos/realm/realm-java/contents/{+path}","compare_url":"https://api.github.com/repos/realm/realm-java/compare/{base}...{head}","merges_url":"https://api.github.com/repos/realm/realm-java/merges","archive_url":"https://api.github.com/repos/realm/realm-java/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/realm/realm-java/downloads","issues_url":"https://api.github.com/repos/realm/realm-java/issues{/number}","pulls_url":"https://api.github.com/repos/realm/realm-java/pulls{/number}","milestones_url":"https://api.github.com/repos/realm/realm-java/milestones{/number}","notifications_url":"https://api.github.com/repos/realm/realm-java/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/realm/realm-java/labels{/name}","releases_url":"https://api.github.com/repos/realm/realm-java/releases{/id}","created_at":"2012-04-20T09:18:42Z","updated_at":"2015-05-07T08:37:00Z","pushed_at":"2015-05-07T08:26:29Z","git_url":"git://github.com/realm/realm-java.git","ssh_url":"git@github.com:realm/realm-java.git","clone_url":"https://github.com/realm/realm-java.git","svn_url":"https://github.com/realm/realm-java","homepage":"http://realm.io","size":55851,"stargazers_count":1721,"watchers_count":1721,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":149,"mirror_url":null,"open_issues_count":113,"forks":149,"open_issues":113,"watchers":1721,"default_branch":"master"}},"base":{"label":"realm:master","ref":"master","sha":"c602bcd82b21a7224ecdfb6d04c6e6c01d6dfd13","user":{"login":"realm","id":7575099,"avatar_url":"https://avatars.githubusercontent.com/u/7575099?v=3","gravatar_id":"","url":"https://api.github.com/users/realm","html_url":"https://github.com/realm","followers_url":"https://api.github.com/users/realm/followers","following_url":"https://api.github.com/users/realm/following{/other_user}","gists_url":"https://api.github.com/users/realm/gists{/gist_id}","starred_url":"https://api.github.com/users/realm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/realm/subscriptions","organizations_url":"https://api.github.com/users/realm/orgs","repos_url":"https://api.github.com/users/realm/repos","events_url":"https://api.github.com/users/realm/events{/privacy}","received_events_url":"https://api.github.com/users/realm/received_events","type":"Organization","site_admin":false},"repo":{"id":4084908,"name":"realm-java","full_name":"realm/realm-java","owner":{"login":"realm","id":7575099,"avatar_url":"https://avatars.githubusercontent.com/u/7575099?v=3","gravatar_id":"","url":"https://api.github.com/users/realm","html_url":"https://github.com/realm","followers_url":"https://api.github.com/users/realm/followers","following_url":"https://api.github.com/users/realm/following{/other_user}","gists_url":"https://api.github.com/users/realm/gists{/gist_id}","starred_url":"https://api.github.com/users/realm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/realm/subscriptions","organizations_url":"https://api.github.com/users/realm/orgs","repos_url":"https://api.github.com/users/realm/repos","events_url":"https://api.github.com/users/realm/events{/privacy}","received_events_url":"https://api.github.com/users/realm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/realm/realm-java","description":"Realm is a mobile database: a replacement for SQLite & ORMs","fork":false,"url":"https://api.github.com/repos/realm/realm-java","forks_url":"https://api.github.com/repos/realm/realm-java/forks","keys_url":"https://api.github.com/repos/realm/realm-java/keys{/key_id}","collaborators_url":"https://api.github.com/repos/realm/realm-java/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/realm/realm-java/teams","hooks_url":"https://api.github.com/repos/realm/realm-java/hooks","issue_events_url":"https://api.github.com/repos/realm/realm-java/issues/events{/number}","events_url":"https://api.github.com/repos/realm/realm-java/events","assignees_url":"https://api.github.com/repos/realm/realm-java/assignees{/user}","branches_url":"https://api.github.com/repos/realm/realm-java/branches{/branch}","tags_url":"https://api.github.com/repos/realm/realm-java/tags","blobs_url":"https://api.github.com/repos/realm/realm-java/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/realm/realm-java/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/realm/realm-java/git/refs{/sha}","trees_url":"https://api.github.com/repos/realm/realm-java/git/trees{/sha}","statuses_url":"https://api.github.com/repos/realm/realm-java/statuses/{sha}","languages_url":"https://api.github.com/repos/realm/realm-java/languages","stargazers_url":"https://api.github.com/repos/realm/realm-java/stargazers","contributors_url":"https://api.github.com/repos/realm/realm-java/contributors","subscribers_url":"https://api.github.com/repos/realm/realm-java/subscribers","subscription_url":"https://api.github.com/repos/realm/realm-java/subscription","commits_url":"https://api.github.com/repos/realm/realm-java/commits{/sha}","git_commits_url":"https://api.github.com/repos/realm/realm-java/git/commits{/sha}","comments_url":"https://api.github.com/repos/realm/realm-java/comments{/number}","issue_comment_url":"https://api.github.com/repos/realm/realm-java/issues/comments{/number}","contents_url":"https://api.github.com/repos/realm/realm-java/contents/{+path}","compare_url":"https://api.github.com/repos/realm/realm-java/compare/{base}...{head}","merges_url":"https://api.github.com/repos/realm/realm-java/merges","archive_url":"https://api.github.com/repos/realm/realm-java/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/realm/realm-java/downloads","issues_url":"https://api.github.com/repos/realm/realm-java/issues{/number}","pulls_url":"https://api.github.com/repos/realm/realm-java/pulls{/number}","milestones_url":"https://api.github.com/repos/realm/realm-java/milestones{/number}","notifications_url":"https://api.github.com/repos/realm/realm-java/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/realm/realm-java/labels{/name}","releases_url":"https://api.github.com/repos/realm/realm-java/releases{/id}","created_at":"2012-04-20T09:18:42Z","updated_at":"2015-05-07T08:37:00Z","pushed_at":"2015-05-07T08:26:29Z","git_url":"git://github.com/realm/realm-java.git","ssh_url":"git@github.com:realm/realm-java.git","clone_url":"https://github.com/realm/realm-java.git","svn_url":"https://github.com/realm/realm-java","homepage":"http://realm.io","size":55851,"stargazers_count":1721,"watchers_count":1721,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":149,"mirror_url":null,"open_issues_count":113,"forks":149,"open_issues":113,"watchers":1721,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/realm/realm-java/pulls/1090"},"html":{"href":"https://github.com/realm/realm-java/pull/1090"},"issue":{"href":"https://api.github.com/repos/realm/realm-java/issues/1090"},"comments":{"href":"https://api.github.com/repos/realm/realm-java/issues/1090/comments"},"review_comments":{"href":"https://api.github.com/repos/realm/realm-java/pulls/1090/comments"},"review_comment":{"href":"https://api.github.com/repos/realm/realm-java/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/realm/realm-java/pulls/1090/commits"},"statuses":{"href":"https://api.github.com/repos/realm/realm-java/statuses/c659a9901738be60a783bfa897c24f640d92806c"}}}}